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
;
74 CGLPBufferObj pbuffer
;
82 static CFMutableDictionaryRef dc_pbuffers
;
84 static CRITICAL_SECTION dc_pbuffers_section
;
85 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
87 0, 0, &dc_pbuffers_section
,
88 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
89 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
91 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
94 static struct opengl_funcs opengl_funcs
;
96 #define USE_GL_FUNC(name) #name,
97 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
101 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
103 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
104 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
105 GLenum format
, GLenum type
, void *pixels
);
106 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
112 GLint color_bits
; /* including alpha_bits */
113 int red_bits
, red_shift
;
114 int green_bits
, green_shift
;
115 int blue_bits
, blue_shift
;
116 GLint alpha_bits
, alpha_shift
;
121 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
122 observations of the behavior of Windows systems, but also subjective judgments
123 about what color formats are more "normal" than others.
125 On at least some Windows systems, integer color formats are listed before
126 floating-point formats. Within the integer formats, higher color bits were
127 usually listed before lower color bits, while for floating-point formats it
128 was the reverse. However, that leads D3D to select 64-bit integer formats in
129 preference to 32-bit formats when the latter would be sufficient. It seems
130 that a 32-bit format is much more likely to be normally used in that case.
132 Also, there are certain odd color formats supported on the Mac which seem like
133 they would be less appropriate than more common ones. For instance, the color
134 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
135 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
138 For two color formats which differ only in whether or not they have alpha bits,
139 we use the same ordering. pixel_format_comparator() gives alpha bits a
140 different weight than color formats.
142 static const struct color_mode color_modes
[] = {
143 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
144 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
145 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
146 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
147 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
148 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
149 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
150 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
151 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
152 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
153 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
154 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
155 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
156 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
157 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
158 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
159 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
160 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
161 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
162 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
163 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
164 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
165 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
166 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
170 static const struct {
173 } depth_stencil_modes
[] = {
201 GLint max_aux_buffers
;
202 GLint max_sample_buffers
;
209 } renderer_properties
;
213 unsigned int window
:1;
214 unsigned int pbuffer
:1;
215 unsigned int accelerated
:1;
216 unsigned int color_mode
:5; /* index into color_modes table */
217 unsigned int aux_buffers
:3;
218 unsigned int depth_bits
:8;
219 unsigned int stencil_bits
:8;
220 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
221 unsigned int double_buffer
:1;
222 unsigned int stereo
:1;
223 unsigned int sample_buffers
:1;
224 unsigned int samples
:5;
225 unsigned int backing_store
:1;
233 } pixel_format_or_code
;
236 static pixel_format
*pixel_formats
;
237 static int nb_formats
, nb_displayable_formats
;
240 static void *opengl_handle
;
243 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
244 CGLRendererProperty property
, GLint
*value
)
246 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
247 if (err
!= kCGLNoError
)
248 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
249 return (err
== kCGLNoError
);
253 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
257 memset(properties
, 0, sizeof(*properties
));
259 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
260 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
262 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
263 properties
->buffer_modes
= value
;
265 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
266 properties
->color_modes
= value
;
268 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
269 properties
->accum_modes
= value
;
271 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
272 properties
->depth_modes
= value
;
274 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
275 properties
->stencil_modes
= value
;
277 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
278 properties
->max_aux_buffers
= value
;
280 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
281 properties
->max_sample_buffers
= value
;
283 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
284 properties
->max_samples
= value
;
286 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
287 properties
->offscreen
= (value
!= 0);
289 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
290 properties
->accelerated
= (value
!= 0);
292 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
293 properties
->backing_store
= (value
!= 0);
295 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
296 properties
->window
= (value
!= 0);
298 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
299 properties
->online
= (value
!= 0);
303 static void dump_renderer(const renderer_properties
* renderer
)
307 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
308 TRACE("Buffer modes:\n");
309 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
310 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
311 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
312 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
314 TRACE("Color buffer modes:\n");
315 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
317 if (renderer
->color_modes
& color_modes
[i
].mode
)
319 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
320 if (color_modes
[i
].is_float
)
326 TRACE("Accumulation buffer sizes: { ");
327 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
329 if (renderer
->accum_modes
& color_modes
[i
].mode
)
330 TRACE("%d, ", color_modes
[i
].color_bits
);
334 TRACE("Depth buffer sizes: { ");
335 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
337 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
338 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
342 TRACE("Stencil buffer sizes: { ");
343 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
345 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
346 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
350 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
351 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
352 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
353 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
354 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
355 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
356 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
357 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
361 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
363 pixel_format_or_code pfc
;
366 pfc
.format
= *format
;
371 static inline pixel_format
pixel_format_for_code(UInt64 code
)
373 pixel_format_or_code pfc
;
380 static const char *debugstr_pf(const pixel_format
*pf
)
382 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",
386 color_modes
[pf
->color_mode
].color_bits
,
387 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
388 color_modes
[pf
->color_mode
].alpha_bits
,
391 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
398 code_for_pixel_format(pf
));
402 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
407 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
409 if ((modes
& color_modes
[i
].mode
) &&
410 color_modes
[i
].color_bits
>= color_size
&&
411 color_modes
[i
].alpha_bits
>= alpha_size
&&
412 !color_modes
[i
].is_float
== !color_float
)
414 if (best
< 0) /* no existing best choice */
416 else if (color_modes
[i
].color_bits
== color_size
&&
417 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
419 /* prefer it over a best which isn't exact or which has a higher bpp */
420 if (color_modes
[best
].color_bits
!= color_size
||
421 color_modes
[best
].alpha_bits
!= alpha_size
||
422 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
425 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
426 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
427 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
434 /* Couldn't find a match. Return first one that renderer supports. */
435 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
437 if (modes
& color_modes
[i
].mode
)
446 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
451 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
453 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
455 /* Prefer the fewest color bits, then prefer more alpha bits, then
456 prefer more bits per pixel. */
459 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
461 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
463 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
465 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
466 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
474 /* Couldn't find a match. Return last one that renderer supports. */
475 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
477 if (modes
& color_modes
[i
].mode
)
486 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
487 CFMutableSetRef pixel_format_set
)
489 CGLPixelFormatAttribute attribs
[64] = {
490 kCGLPFAMinimumPolicy
,
491 kCGLPFAClosestPolicy
,
492 kCGLPFARendererID
, renderer
.renderer_id
,
493 kCGLPFASingleRenderer
,
495 int n
= 5, n_stack
[16], n_stack_idx
= -1;
496 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
497 new_pixel_formats
= 0;
498 pixel_format request
;
499 unsigned int double_buffer
;
500 unsigned int accelerated
= renderer
.accelerated
;
504 attribs
[n
++] = kCGLPFAAccelerated
;
505 attribs
[n
++] = kCGLPFANoRecovery
;
508 n_stack
[++n_stack_idx
] = n
;
509 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
513 n
= n_stack
[n_stack_idx
];
515 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
516 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
520 attribs
[n
++] = kCGLPFADoubleBuffer
;
521 memset(&request
, 0, sizeof(request
));
522 request
.accelerated
= accelerated
;
523 request
.double_buffer
= double_buffer
;
525 /* Don't bother with in-between aux buffers values: either 0 or max. */
526 n_stack
[++n_stack_idx
] = n
;
527 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
529 unsigned int color_mode
;
531 n
= n_stack
[n_stack_idx
];
533 attribs
[n
++] = kCGLPFAAuxBuffers
;
535 request
.aux_buffers
= aux
;
537 n_stack
[++n_stack_idx
] = n
;
538 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
540 unsigned int depth_mode
;
542 n
= n_stack
[n_stack_idx
];
544 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
547 attribs
[n
++] = kCGLPFAColorSize
;
548 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
549 attribs
[n
++] = kCGLPFAAlphaSize
;
550 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
551 if (color_modes
[color_mode
].is_float
)
552 attribs
[n
++] = kCGLPFAColorFloat
;
553 request
.color_mode
= color_mode
;
555 n_stack
[++n_stack_idx
] = n
;
556 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
558 unsigned int stencil_mode
;
560 n
= n_stack
[n_stack_idx
];
562 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
565 attribs
[n
++] = kCGLPFADepthSize
;
566 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
567 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
569 n_stack
[++n_stack_idx
] = n
;
570 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
574 n
= n_stack
[n_stack_idx
];
576 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
578 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
581 attribs
[n
++] = kCGLPFAStencilSize
;
582 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
583 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
585 /* FIXME: Could trim search space a bit here depending on GPU.
586 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
587 n_stack
[++n_stack_idx
] = n
;
588 for (stereo
= 0; stereo
<= 1; stereo
++)
592 n
= n_stack
[n_stack_idx
];
594 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
595 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
599 attribs
[n
++] = kCGLPFAStereo
;
600 request
.stereo
= stereo
;
602 /* Starts at -1 for a 0 accum size */
603 n_stack
[++n_stack_idx
] = n
;
604 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
606 unsigned int target_pass
;
608 n
= n_stack
[n_stack_idx
];
612 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
615 attribs
[n
++] = kCGLPFAAccumSize
;
616 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
617 request
.accum_mode
= accum_mode
+ 1;
620 request
.accum_mode
= 0;
622 /* Targets to request are:
623 accelerated: window OR window + pbuffer
624 software: window + pbuffer */
625 n_stack
[++n_stack_idx
] = n
;
626 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
628 unsigned int samples
, max_samples
;
630 n
= n_stack
[n_stack_idx
];
632 attribs
[n
++] = kCGLPFAWindow
;
635 if (!accelerated
|| target_pass
> 0)
637 attribs
[n
++] = kCGLPFAPBuffer
;
643 /* FIXME: Could trim search space a bit here depending on GPU.
644 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
645 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
646 n_stack
[++n_stack_idx
] = n
;
647 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
648 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
650 unsigned int backing_store
, min_backing_store
, max_backing_store
;
652 n
= n_stack
[n_stack_idx
];
656 attribs
[n
++] = kCGLPFASampleBuffers
;
657 attribs
[n
++] = renderer
.max_sample_buffers
;
658 attribs
[n
++] = kCGLPFASamples
;
659 attribs
[n
++] = samples
;
660 request
.sample_buffers
= renderer
.max_sample_buffers
;
661 request
.samples
= samples
;
664 request
.sample_buffers
= request
.samples
= 0;
666 if (renderer
.backing_store
&& double_buffer
)
668 /* The software renderer seems to always preserve the backing store, whether
669 we ask for it or not. So don't bother not asking for it. */
670 min_backing_store
= accelerated
? 0 : 1;
671 max_backing_store
= 1;
674 min_backing_store
= max_backing_store
= 0;
675 n_stack
[++n_stack_idx
] = n
;
676 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
678 CGLPixelFormatObj pix
;
679 GLint virtualScreens
;
682 n
= n_stack
[n_stack_idx
];
685 attribs
[n
++] = kCGLPFABackingStore
;
686 request
.backing_store
= backing_store
;
690 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
691 if (err
== kCGLNoError
&& pix
)
694 GLint value
, color_size
, alpha_size
, color_float
;
696 CFNumberRef code_object
;
699 memset(&pf
, 0, sizeof(pf
));
701 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
702 pf
.accelerated
= value
;
703 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
704 pf
.aux_buffers
= value
;
705 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
706 pf
.depth_bits
= value
;
707 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
708 pf
.double_buffer
= value
;
709 if (pf
.double_buffer
&&
710 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
711 pf
.backing_store
= value
;
712 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
714 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
715 pf
.sample_buffers
= value
;
716 if (pf
.sample_buffers
&&
717 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
719 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
720 pf
.stencil_bits
= value
;
721 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
723 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
726 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
728 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
730 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
732 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
734 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
735 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
737 CGLReleasePixelFormat(pix
);
739 pf_code
= code_for_pixel_format(&pf
);
741 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
742 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
743 dupe_pixel_formats
++;
746 CFSetAddValue(pixel_format_set
, code_object
);
747 CFArrayAppendValue(pixel_format_array
, code_object
);
750 CFRelease(code_object
);
752 if (pf_code
== code_for_pixel_format(&request
))
753 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
756 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
757 dupe
? " (duplicate)" : "");
762 failed_pixel_formats
++;
763 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
766 tried_pixel_formats
++;
798 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
799 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
800 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
801 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
805 /* The docs for WGL_ARB_pixel_format say:
806 Indices are assigned to pixel formats in the following order:
807 1. Accelerated pixel formats that are displayable
808 2. Accelerated pixel formats that are displayable and which have
810 3. Generic pixel formats
811 4. Accelerated pixel formats that are non displayable
813 static int pixel_format_category(pixel_format pf
)
815 /* non-displayable */
819 /* non-accelerated a.k.a. software a.k.a. generic */
823 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
824 if (color_modes
[pf
.color_mode
].is_float
)
827 /* accelerated, displayable, no extended attributes */
832 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
834 CFNumberRef number1
= val1
;
835 CFNumberRef number2
= val2
;
837 pixel_format pf1
, pf2
;
838 int category1
, category2
;
840 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
841 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
842 pf1
= pixel_format_for_code(code1
);
843 pf2
= pixel_format_for_code(code2
);
844 category1
= pixel_format_category(pf1
);
845 category2
= pixel_format_category(pf2
);
847 if (category1
< category2
)
848 return kCFCompareLessThan
;
849 if (category1
> category2
)
850 return kCFCompareGreaterThan
;
852 /* Within a category, sort the "best" formats toward the front since that's
853 what wglChoosePixelFormatARB() has to do. The ordering implemented here
854 matches at least one Windows 7 machine's behavior.
856 /* Accelerated before unaccelerated. */
857 if (pf1
.accelerated
&& !pf2
.accelerated
)
858 return kCFCompareLessThan
;
859 if (!pf1
.accelerated
&& pf2
.accelerated
)
860 return kCFCompareGreaterThan
;
862 /* Explicit color mode ordering. */
863 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
864 return kCFCompareLessThan
;
865 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
866 return kCFCompareGreaterThan
;
868 /* Non-pbuffer-capable before pbuffer-capable. */
869 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
870 return kCFCompareLessThan
;
871 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
872 return kCFCompareGreaterThan
;
874 /* Fewer samples before more samples. */
875 if (pf1
.samples
< pf2
.samples
)
876 return kCFCompareLessThan
;
877 if (pf1
.samples
> pf2
.samples
)
878 return kCFCompareGreaterThan
;
880 /* Monoscopic before stereoscopic. (This is a guess.) */
881 if (!pf1
.stereo
&& pf2
.stereo
)
882 return kCFCompareLessThan
;
883 if (pf1
.stereo
&& !pf2
.stereo
)
884 return kCFCompareGreaterThan
;
886 /* Single buffered before double buffered. */
887 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
888 return kCFCompareLessThan
;
889 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
890 return kCFCompareGreaterThan
;
892 /* Possibly-optimized double buffering before backing-store-preserving
894 if (!pf1
.backing_store
&& pf2
.backing_store
)
895 return kCFCompareLessThan
;
896 if (pf1
.backing_store
&& !pf2
.backing_store
)
897 return kCFCompareGreaterThan
;
899 /* Bigger depth buffer before smaller depth buffer. */
900 if (pf1
.depth_bits
> pf2
.depth_bits
)
901 return kCFCompareLessThan
;
902 if (pf1
.depth_bits
< pf2
.depth_bits
)
903 return kCFCompareGreaterThan
;
905 /* Smaller stencil buffer before bigger stencil buffer. */
906 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
907 return kCFCompareLessThan
;
908 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
909 return kCFCompareGreaterThan
;
911 /* Smaller alpha bits before larger alpha bits. */
912 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
913 return kCFCompareLessThan
;
914 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
915 return kCFCompareGreaterThan
;
917 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
922 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
923 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
924 return kCFCompareLessThan
;
925 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
926 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
927 return kCFCompareGreaterThan
;
929 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
930 return kCFCompareLessThan
;
931 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
932 return kCFCompareGreaterThan
;
934 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
935 return kCFCompareLessThan
;
936 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
937 return kCFCompareGreaterThan
;
940 return kCFCompareGreaterThan
;
942 else if (pf2
.accum_mode
)
943 return kCFCompareLessThan
;
945 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
946 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
947 return kCFCompareLessThan
;
948 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
949 return kCFCompareGreaterThan
;
951 /* If we get here, arbitrarily sort based on code. */
953 return kCFCompareLessThan
;
955 return kCFCompareGreaterThan
;
956 return kCFCompareEqualTo
;
960 static BOOL
init_pixel_formats(void)
963 CGLRendererInfoObj renderer_info
;
966 CFMutableSetRef pixel_format_set
;
967 CFMutableArrayRef pixel_format_array
;
973 assert(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
975 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
978 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
982 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
983 if (!pixel_format_set
)
985 WARN("CFSetCreateMutable failed\n");
986 CGLDestroyRendererInfo(renderer_info
);
990 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
991 if (!pixel_format_array
)
993 WARN("CFArrayCreateMutable failed\n");
994 CFRelease(pixel_format_set
);
995 CGLDestroyRendererInfo(renderer_info
);
999 for (i
= 0; i
< rendererCount
; i
++)
1001 renderer_properties renderer
;
1003 get_renderer_properties(renderer_info
, i
, &renderer
);
1006 TRACE("renderer_properties %d:\n", i
);
1007 dump_renderer(&renderer
);
1010 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1013 CFRelease(pixel_format_set
);
1014 CGLDestroyRendererInfo(renderer_info
);
1016 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1019 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1022 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1023 for (i
= 0; i
< range
.length
; i
++)
1025 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1028 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1029 pixel_formats
[i
] = pixel_format_for_code(code
);
1030 if (pixel_formats
[i
].window
)
1031 nb_displayable_formats
++;
1034 nb_formats
= range
.length
;
1035 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1039 WARN("failed to allocate pixel format list\n");
1042 WARN("got no pixel formats\n");
1044 CFRelease(pixel_format_array
);
1049 static inline BOOL
is_valid_pixel_format(int format
)
1051 return format
> 0 && format
<= nb_formats
;
1055 static inline BOOL
is_displayable_pixel_format(int format
)
1057 return format
> 0 && format
<= nb_displayable_formats
;
1061 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1063 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1064 * format in case of probing the number of pixel formats.
1066 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1068 TRACE("Returning format %d\n", format
);
1069 return &pixel_formats
[format
- 1];
1075 static BOOL
init_gl_info(void)
1077 CGDirectDisplayID display
= CGMainDisplayID();
1078 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1079 CGLPixelFormatAttribute attribs
[] = {
1080 kCGLPFADisplayMask
, displayMask
,
1083 CGLPixelFormatObj pix
;
1084 GLint virtualScreens
;
1086 CGLContextObj context
;
1087 CGLContextObj old_context
= CGLGetCurrentContext();
1090 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1091 if (err
!= kCGLNoError
|| !pix
)
1093 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1097 err
= CGLCreateContext(pix
, NULL
, &context
);
1098 CGLReleasePixelFormat(pix
);
1099 if (err
!= kCGLNoError
|| !context
)
1101 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1105 err
= CGLSetCurrentContext(context
);
1106 if (err
!= kCGLNoError
)
1108 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1109 CGLReleaseContext(context
);
1113 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1114 gl_info
.glVersion
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1115 strcpy(gl_info
.glVersion
, str
);
1116 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1117 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1118 strcpy(gl_info
.glExtensions
, str
);
1120 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1122 TRACE("GL version : %s\n", gl_info
.glVersion
);
1123 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1125 CGLSetCurrentContext(old_context
);
1126 CGLReleaseContext(context
);
1132 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1135 *rect
= data
->client_rect
;
1137 if (data
->cocoa_window
)
1140 *window
= data
->cocoa_window
;
1141 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1145 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1146 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1147 struct macdrv_win_data
*top_data
= get_win_data(top
);
1149 if (top_data
&& top_data
->cocoa_window
)
1152 *window
= top_data
->cocoa_window
;
1153 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1154 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1159 release_win_data(top_data
);
1166 /***********************************************************************
1169 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1171 macdrv_window cocoa_window
;
1173 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1175 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1177 ERR("no top-level parent with Cocoa window in this process\n");
1181 if (data
->gl_view
) macdrv_dispose_view(data
->gl_view
);
1182 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1186 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1190 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1191 wine_dbgstr_rect(&data
->gl_rect
));
1193 data
->pixel_format
= format
;
1199 /**********************************************************************
1202 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1204 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1206 struct macdrv_win_data
*data
;
1207 const pixel_format
*pf
;
1208 HWND hwnd
= WindowFromDC(hdc
);
1211 TRACE("hdc %p format %d\n", hdc
, fmt
);
1213 if (!hwnd
|| hwnd
== GetDesktopWindow())
1215 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1219 if (!(data
= get_win_data(hwnd
)))
1221 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1225 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1227 ret
= (data
->pixel_format
== fmt
);
1231 /* Check if fmt is in our list of supported formats to see if it is supported. */
1232 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1235 ERR("Invalid pixel format: %d\n", fmt
);
1241 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1245 if (!set_win_format(data
, fmt
))
1247 WARN("Couldn't set format of the window, returning failure\n");
1251 TRACE("pixel format:\n");
1252 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1253 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1254 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1255 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1256 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1257 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1258 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1259 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1260 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1261 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1262 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1263 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1264 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1265 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1269 release_win_data(data
);
1270 if (ret
) __wine_set_pixel_format(hwnd
, fmt
);
1275 /**********************************************************************
1276 * set_gl_view_parent
1278 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1280 struct macdrv_win_data
*data
;
1282 if (!(data
= get_win_data(hwnd
))) return;
1286 macdrv_window cocoa_window
;
1288 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1290 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1292 ERR("no top-level parent with Cocoa window in this process\n");
1293 macdrv_dispose_view(data
->gl_view
);
1294 data
->gl_view
= NULL
;
1295 release_win_data(data
);
1296 __wine_set_pixel_format( hwnd
, 0 );
1300 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1303 release_win_data(data
);
1307 /**********************************************************************
1308 * make_context_current
1310 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1313 struct wgl_pbuffer
*pbuffer
;
1317 view
= context
->read_view
;
1318 pbuffer
= context
->read_pbuffer
;
1322 view
= context
->draw_view
;
1323 pbuffer
= context
->draw_pbuffer
;
1326 if (view
|| !pbuffer
)
1327 macdrv_make_context_current(context
->context
, view
);
1330 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1332 CGLSetCurrentContext(context
->cglcontext
);
1337 /**********************************************************************
1338 * macdrv_glCopyColorTable
1340 * Hook into glCopyColorTable as part of the implementation of
1341 * wglMakeContextCurrentARB. If the context has a separate readable,
1342 * temporarily make that current, do glCopyColorTable, and then set it
1343 * back to the drawable. This is modeled after what Mesa GLX's Apple
1344 * implementation does.
1346 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1349 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1351 if (context
->read_view
|| context
->read_pbuffer
)
1352 make_context_current(context
, TRUE
);
1354 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1356 if (context
->read_view
|| context
->read_pbuffer
)
1357 make_context_current(context
, FALSE
);
1361 /**********************************************************************
1362 * macdrv_glCopyPixels
1364 * Hook into glCopyPixels as part of the implementation of
1365 * wglMakeContextCurrentARB. If the context has a separate readable,
1366 * temporarily make that current, do glCopyPixels, and then set it back
1367 * to the drawable. This is modeled after what Mesa GLX's Apple
1368 * implementation does.
1370 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1372 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1374 if (context
->read_view
|| context
->read_pbuffer
)
1375 make_context_current(context
, TRUE
);
1377 pglCopyPixels(x
, y
, width
, height
, type
);
1379 if (context
->read_view
|| context
->read_pbuffer
)
1380 make_context_current(context
, FALSE
);
1384 /**********************************************************************
1385 * macdrv_glReadPixels
1387 * Hook into glReadPixels as part of the implementation of
1388 * wglMakeContextCurrentARB. If the context has a separate readable,
1389 * temporarily make that current, do glReadPixels, and then set it back
1390 * to the drawable. This is modeled after what Mesa GLX's Apple
1391 * implementation does.
1393 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1394 GLenum format
, GLenum type
, void *pixels
)
1396 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1398 if (context
->read_view
|| context
->read_pbuffer
)
1399 make_context_current(context
, TRUE
);
1401 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1403 if (context
->read_view
|| context
->read_pbuffer
)
1404 make_context_current(context
, FALSE
);
1408 /**********************************************************************
1411 * Hook into glViewport as an opportunity to update the OpenGL context
1412 * if necessary. This is modeled after what Mesa GLX's Apple
1413 * implementation does.
1415 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1417 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1419 macdrv_update_opengl_context(context
->context
);
1420 pglViewport(x
, y
, width
, height
);
1424 /***********************************************************************
1425 * macdrv_wglBindTexImageARB
1427 * WGL_ARB_render_texture: wglBindTexImageARB
1429 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1431 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1435 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1437 if (pbuffer
->no_texture
)
1439 SetLastError(ERROR_INVALID_OPERATION
);
1443 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1444 opengl_funcs
.gl
.p_glFlush();
1448 case WGL_FRONT_LEFT_ARB
:
1449 if (pixel_formats
[pbuffer
->format
].stereo
)
1450 source
= GL_FRONT_LEFT
;
1454 case WGL_FRONT_RIGHT_ARB
:
1455 source
= GL_FRONT_RIGHT
;
1457 case WGL_BACK_LEFT_ARB
:
1458 if (pixel_formats
[pbuffer
->format
].stereo
)
1459 source
= GL_BACK_LEFT
;
1463 case WGL_BACK_RIGHT_ARB
:
1464 source
= GL_BACK_RIGHT
;
1466 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1467 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1468 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1469 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1477 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1478 SetLastError(ERROR_INVALID_DATA
);
1482 WARN("unknown source buffer 0x%x\n", iBuffer
);
1483 SetLastError(ERROR_INVALID_DATA
);
1487 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1488 if (err
!= kCGLNoError
)
1490 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1491 SetLastError(ERROR_INVALID_OPERATION
);
1499 /***********************************************************************
1500 * macdrv_wglChoosePixelFormatARB
1502 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1504 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
1505 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
1506 int *piFormats
, UINT
*nNumFormats
)
1508 pixel_format pf
, valid
;
1510 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
1511 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
1516 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1517 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
1519 FIXME("unused pfAttribFList\n");
1521 memset(&pf
, 0, sizeof(pf
));
1522 memset(&valid
, 0, sizeof(valid
));
1523 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
1524 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
1528 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
1531 int value
= iptr
[1];
1535 case WGL_DRAW_TO_WINDOW_ARB
:
1536 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
1537 pf
.window
= (value
!= 0);
1541 case WGL_DRAW_TO_BITMAP_ARB
:
1544 case WGL_ACCELERATION_ARB
:
1545 if (value
== WGL_FULL_ACCELERATION_ARB
)
1547 else if (value
== WGL_NO_ACCELERATION_ARB
)
1551 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
1552 pf
.accelerated
= value
;
1553 valid
.accelerated
= 1;
1556 case WGL_NEED_PALETTE_ARB
:
1557 case WGL_NEED_SYSTEM_PALETTE_ARB
:
1558 case WGL_SWAP_LAYER_BUFFERS_ARB
:
1559 if (value
) goto cant_match
;
1562 case WGL_SWAP_METHOD_ARB
:
1563 if (value
== WGL_SWAP_COPY_ARB
)
1565 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
1569 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
1570 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
1571 pf
.backing_store
= value
;
1572 valid
.backing_store
= 1;
1575 case WGL_NUMBER_OVERLAYS_ARB
:
1576 case WGL_NUMBER_UNDERLAYS_ARB
:
1577 if (value
) goto cant_match
;
1580 case WGL_SHARE_DEPTH_ARB
:
1581 case WGL_SHARE_STENCIL_ARB
:
1582 case WGL_SHARE_ACCUM_ARB
:
1586 case WGL_SUPPORT_GDI_ARB
:
1587 if (value
) goto cant_match
;
1590 case WGL_SUPPORT_OPENGL_ARB
:
1591 if (!value
) goto cant_match
;
1594 case WGL_DOUBLE_BUFFER_ARB
:
1595 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
1596 pf
.double_buffer
= (value
!= 0);
1597 valid
.double_buffer
= 1;
1598 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
1601 case WGL_STEREO_ARB
:
1602 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
1603 pf
.stereo
= (value
!= 0);
1607 case WGL_PIXEL_TYPE_ARB
:
1608 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
1610 else if (value
== WGL_TYPE_RGBA_ARB
)
1614 /* Mac contexts don't support rendering to unsigned floating
1615 point formats, even if GL_EXT_packed_float is supported.
1616 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1619 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
1620 if (srgb
&& value
) goto cant_match
;
1621 float_color
= value
;
1624 case WGL_COLOR_BITS_ARB
:
1625 if (color_bits
< value
) color_bits
= value
;
1628 case WGL_RED_BITS_ARB
:
1629 if (srgb
&& value
> 8) goto cant_match
;
1630 if (red_bits
< value
) red_bits
= value
;
1633 case WGL_GREEN_BITS_ARB
:
1634 if (srgb
&& value
> 8) goto cant_match
;
1635 if (green_bits
< value
) green_bits
= value
;
1638 case WGL_BLUE_BITS_ARB
:
1639 if (srgb
&& value
> 8) goto cant_match
;
1640 if (blue_bits
< value
) blue_bits
= value
;
1643 case WGL_ALPHA_BITS_ARB
:
1644 if (alpha_bits
< value
) alpha_bits
= value
;
1647 case WGL_ACCUM_BITS_ARB
:
1648 if (accum_bits
< value
) accum_bits
= value
;
1651 case WGL_ACCUM_RED_BITS_ARB
:
1652 if (accum_red_bits
< value
) accum_red_bits
= value
;
1655 case WGL_ACCUM_GREEN_BITS_ARB
:
1656 if (accum_green_bits
< value
) accum_green_bits
= value
;
1659 case WGL_ACCUM_BLUE_BITS_ARB
:
1660 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
1663 case WGL_ACCUM_ALPHA_BITS_ARB
:
1664 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
1667 case WGL_DEPTH_BITS_ARB
:
1668 if (value
> 255) goto cant_match
;
1669 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
1672 case WGL_STENCIL_BITS_ARB
:
1673 if (value
> 255) goto cant_match
;
1674 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
1677 case WGL_AUX_BUFFERS_ARB
:
1678 if (value
> 7) goto cant_match
;
1679 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
1682 case WGL_SAMPLE_BUFFERS_ARB
:
1683 if (value
> 1) goto cant_match
;
1684 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
1687 case WGL_SAMPLES_ARB
:
1688 if (value
> 31) goto cant_match
;
1689 if (pf
.samples
< value
) pf
.samples
= value
;
1692 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1693 /* sRGB is only supported for 8-bit integer color components */
1694 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
1699 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
1700 case WGL_RED_SHIFT_ARB
:
1701 case WGL_GREEN_SHIFT_ARB
:
1702 case WGL_BLUE_SHIFT_ARB
:
1703 case WGL_ALPHA_SHIFT_ARB
:
1704 case WGL_TRANSPARENT_ARB
:
1705 case WGL_TRANSPARENT_RED_VALUE_ARB
:
1706 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
1707 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
1708 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
1709 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
1713 case WGL_DRAW_TO_PBUFFER_ARB
:
1714 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
1715 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
1716 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
1717 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
1718 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
1719 pf
.pbuffer
= (value
!= 0);
1721 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
1727 WARN("invalid attribute %x\n", iptr
[0]);
1732 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
1734 const struct color_mode
*mode
;
1736 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
1737 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
1738 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
1739 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
1740 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
1741 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
1743 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
1744 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
1745 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
1746 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
1747 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
1749 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
1750 /* If the mode doesn't have alpha, check requested color bits against
1751 bits per pixel instead of the mode's color bits. On Windows, color
1752 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1753 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1754 expects that to match such a pixel format, we need to accomodate that. */
1755 if (mode
->alpha_bits
)
1757 if (mode
->color_bits
< color_bits
)
1762 if (mode
->bits_per_pixel
< color_bits
)
1765 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
1766 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
1768 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
1769 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
1772 if (pixel_formats
[i
].accum_mode
)
1774 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
1775 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
1776 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
1777 mode
->alpha_bits
< accum_alpha_bits
)
1780 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
1783 piFormats
[found
++] = i
;
1787 *nNumFormats
= found
;
1793 /**********************************************************************
1794 * macdrv_wglCreatePbufferARB
1796 * WGL_ARB_pbuffer: wglCreatePbufferARB
1798 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
1799 const int *piAttribList
)
1801 struct wgl_pbuffer
* pbuffer
;
1803 GLenum internalFormat
= 0;
1806 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
1807 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
1809 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
].pbuffer
)
1811 WARN("invalid pixel format %d\n", iPixelFormat
);
1812 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1816 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
1817 pbuffer
->format
= iPixelFormat
;
1819 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
1821 int attr
= piAttribList
[0];
1822 int value
= piAttribList
[1];
1826 case WGL_PBUFFER_LARGEST_ARB
:
1827 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
1830 case WGL_TEXTURE_FORMAT_ARB
:
1833 case WGL_TEXTURE_RGBA_ARB
:
1834 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
1835 internalFormat
= GL_RGBA
;
1837 case WGL_TEXTURE_RGB_ARB
:
1838 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
1839 internalFormat
= GL_RGB
;
1841 case WGL_NO_TEXTURE_ARB
:
1842 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
1846 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
1847 SetLastError(ERROR_INVALID_DATA
);
1852 case WGL_TEXTURE_TARGET_ARB
:
1856 case WGL_NO_TEXTURE_ARB
:
1857 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
1860 case WGL_TEXTURE_CUBE_MAP_ARB
:
1861 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
1862 target
= GL_TEXTURE_CUBE_MAP
;
1863 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
1865 case WGL_TEXTURE_1D_ARB
:
1866 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
1867 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
1869 case WGL_TEXTURE_2D_ARB
:
1870 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
1871 target
= GL_TEXTURE_2D
;
1873 case WGL_TEXTURE_RECTANGLE_NV
:
1874 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
1875 target
= GL_TEXTURE_RECTANGLE
;
1878 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
1879 SetLastError(ERROR_INVALID_DATA
);
1884 case WGL_MIPMAP_TEXTURE_ARB
:
1885 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
1886 pbuffer
->max_level
= 0;
1889 int size
= min(iWidth
, iHeight
) / 2;
1892 pbuffer
->max_level
++;
1899 WARN("unknown attribute 0x%x\n", attr
);
1900 SetLastError(ERROR_INVALID_DATA
);
1905 if (!target
|| !internalFormat
)
1907 pbuffer
->no_texture
= TRUE
;
1908 /* no actual way to turn off ability to texture; use most permissive target */
1909 target
= GL_TEXTURE_RECTANGLE
;
1910 internalFormat
= GL_RGB
;
1913 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
1914 if (err
!= kCGLNoError
)
1916 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
1917 pbuffer
->pbuffer
= NULL
;
1918 if (err
== kCGLBadAlloc
)
1919 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
1921 SetLastError(ERROR_INVALID_DATA
);
1925 if (!pbuffer
->pbuffer
)
1927 HeapFree(GetProcessHeap(), 0, pbuffer
);
1931 TRACE(" -> %p\n", pbuffer
);
1936 /**********************************************************************
1937 * macdrv_wglDestroyPbufferARB
1939 * WGL_ARB_pbuffer: wglDestroyPbufferARB
1941 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
1943 TRACE("pbuffer %p\n", pbuffer
);
1944 if (pbuffer
&& pbuffer
->pbuffer
)
1945 CGLReleasePBuffer(pbuffer
->pbuffer
);
1946 HeapFree(GetProcessHeap(), 0, pbuffer
);
1951 /**********************************************************************
1952 * macdrv_wglGetExtensionsStringARB
1954 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
1956 static const GLubyte
*macdrv_wglGetExtensionsStringARB(HDC hdc
)
1958 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
1959 this can be specific to the CGL renderer like we're supposed to do. */
1960 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
1961 return (const GLubyte
*)gl_info
.wglExtensions
;
1965 /**********************************************************************
1966 * macdrv_wglGetExtensionsStringEXT
1968 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
1970 static const GLubyte
*macdrv_wglGetExtensionsStringEXT(void)
1972 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
1973 return (const GLubyte
*)gl_info
.wglExtensions
;
1977 /**********************************************************************
1978 * macdrv_wglGetPbufferDCARB
1980 * WGL_ARB_pbuffer: wglGetPbufferDCARB
1982 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
1985 struct wgl_pbuffer
*prev
;
1987 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1990 EnterCriticalSection(&dc_pbuffers_section
);
1991 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1994 CGLReleasePBuffer(prev
->pbuffer
);
1995 HeapFree(GetProcessHeap(), 0, prev
);
1997 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
1998 LeaveCriticalSection(&dc_pbuffers_section
);
2000 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2005 /**********************************************************************
2006 * macdrv_wglGetPixelFormatAttribivARB
2008 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2010 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2011 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2013 const pixel_format
*pf
;
2016 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2017 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2019 if (!nAttributes
) return GL_TRUE
;
2021 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2023 piValues
[0] = nb_formats
;
2027 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2030 WARN("invalid pixel format %d\n", iPixelFormat
);
2031 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2035 for (i
= 0; i
< nAttributes
; ++i
)
2037 switch (piAttributes
[i
])
2039 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2040 piValues
[i
] = nb_formats
;
2043 case WGL_DRAW_TO_WINDOW_ARB
:
2044 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2047 case WGL_DRAW_TO_BITMAP_ARB
:
2048 piValues
[i
] = GL_FALSE
;
2051 case WGL_ACCELERATION_ARB
:
2052 if (iLayerPlane
) goto invalid_layer
;
2053 if (pf
->accelerated
)
2054 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2056 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2059 case WGL_NEED_PALETTE_ARB
:
2060 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2061 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2062 piValues
[i
] = GL_FALSE
;
2065 case WGL_SWAP_METHOD_ARB
:
2066 if (pf
->double_buffer
&& pf
->backing_store
)
2067 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2069 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2072 case WGL_NUMBER_OVERLAYS_ARB
:
2073 case WGL_NUMBER_UNDERLAYS_ARB
:
2077 case WGL_TRANSPARENT_ARB
:
2078 if (iLayerPlane
) goto invalid_layer
;
2079 piValues
[i
] = GL_FALSE
;
2082 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2083 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2084 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2085 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2086 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2087 if (iLayerPlane
) goto invalid_layer
;
2091 case WGL_SHARE_DEPTH_ARB
:
2092 case WGL_SHARE_STENCIL_ARB
:
2093 case WGL_SHARE_ACCUM_ARB
:
2094 if (iLayerPlane
) goto invalid_layer
;
2095 piValues
[i
] = GL_TRUE
;
2098 case WGL_SUPPORT_GDI_ARB
:
2099 if (iLayerPlane
) goto invalid_layer
;
2100 piValues
[i
] = GL_FALSE
;
2103 case WGL_SUPPORT_OPENGL_ARB
:
2104 if (iLayerPlane
) goto invalid_layer
;
2105 piValues
[i
] = GL_TRUE
;
2108 case WGL_DOUBLE_BUFFER_ARB
:
2109 if (iLayerPlane
) goto invalid_layer
;
2110 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2113 case WGL_STEREO_ARB
:
2114 if (iLayerPlane
) goto invalid_layer
;
2115 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2118 case WGL_PIXEL_TYPE_ARB
:
2119 if (iLayerPlane
) goto invalid_layer
;
2120 if (color_modes
[pf
->color_mode
].is_float
)
2121 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2123 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2124 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2125 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2126 However, Mac contexts don't support rendering to unsigned floating-point
2127 formats, even when GL_EXT_packed_float is supported. */
2130 case WGL_COLOR_BITS_ARB
:
2131 if (iLayerPlane
) goto invalid_layer
;
2132 /* If the mode doesn't have alpha, return bits per pixel instead
2133 of color bits. On Windows, color bits sometimes exceeds r+g+b
2134 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2135 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2136 pixel format, we need to accomodate that. */
2137 if (color_modes
[pf
->color_mode
].alpha_bits
)
2138 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2140 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2143 case WGL_RED_BITS_ARB
:
2144 if (iLayerPlane
) goto invalid_layer
;
2145 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2148 case WGL_RED_SHIFT_ARB
:
2149 if (iLayerPlane
) goto invalid_layer
;
2150 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2153 case WGL_GREEN_BITS_ARB
:
2154 if (iLayerPlane
) goto invalid_layer
;
2155 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2158 case WGL_GREEN_SHIFT_ARB
:
2159 if (iLayerPlane
) goto invalid_layer
;
2160 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2163 case WGL_BLUE_BITS_ARB
:
2164 if (iLayerPlane
) goto invalid_layer
;
2165 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2168 case WGL_BLUE_SHIFT_ARB
:
2169 if (iLayerPlane
) goto invalid_layer
;
2170 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2173 case WGL_ALPHA_BITS_ARB
:
2174 if (iLayerPlane
) goto invalid_layer
;
2175 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2178 case WGL_ALPHA_SHIFT_ARB
:
2179 if (iLayerPlane
) goto invalid_layer
;
2180 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2183 case WGL_ACCUM_BITS_ARB
:
2184 if (iLayerPlane
) goto invalid_layer
;
2186 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2191 case WGL_ACCUM_RED_BITS_ARB
:
2192 if (iLayerPlane
) goto invalid_layer
;
2194 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2199 case WGL_ACCUM_GREEN_BITS_ARB
:
2200 if (iLayerPlane
) goto invalid_layer
;
2202 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2207 case WGL_ACCUM_BLUE_BITS_ARB
:
2208 if (iLayerPlane
) goto invalid_layer
;
2210 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2215 case WGL_ACCUM_ALPHA_BITS_ARB
:
2216 if (iLayerPlane
) goto invalid_layer
;
2218 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2223 case WGL_DEPTH_BITS_ARB
:
2224 if (iLayerPlane
) goto invalid_layer
;
2225 piValues
[i
] = pf
->depth_bits
;
2228 case WGL_STENCIL_BITS_ARB
:
2229 if (iLayerPlane
) goto invalid_layer
;
2230 piValues
[i
] = pf
->stencil_bits
;
2233 case WGL_AUX_BUFFERS_ARB
:
2234 if (iLayerPlane
) goto invalid_layer
;
2235 piValues
[i
] = pf
->aux_buffers
;
2238 case WGL_SAMPLE_BUFFERS_ARB
:
2239 if (iLayerPlane
) goto invalid_layer
;
2240 piValues
[i
] = pf
->sample_buffers
;
2243 case WGL_SAMPLES_ARB
:
2244 if (iLayerPlane
) goto invalid_layer
;
2245 piValues
[i
] = pf
->samples
;
2248 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2249 if (iLayerPlane
) goto invalid_layer
;
2250 /* sRGB is only supported for 8-bit integer color components */
2251 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2252 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2253 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2254 !color_modes
[pf
->color_mode
].is_float
)
2255 piValues
[i
] = GL_TRUE
;
2257 piValues
[i
] = GL_FALSE
;
2260 case WGL_DRAW_TO_PBUFFER_ARB
:
2261 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2262 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2263 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2266 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2267 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2268 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2271 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2272 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2275 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2276 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2279 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2280 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2284 WARN("invalid attribute %x\n", piAttributes
[i
]);
2288 TRACE("piAttributes[%d] (%x) -> %x\n", i
, piAttributes
[i
], piValues
[i
]);
2294 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2299 /**********************************************************************
2300 * macdrv_wglGetPixelFormatAttribfvARB
2302 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2304 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2305 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2310 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2311 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2313 /* Allocate a temporary array to store integer values */
2314 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2317 ERR("couldn't allocate %d array\n", nAttributes
);
2321 /* Piggy-back on wglGetPixelFormatAttribivARB */
2322 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2327 /* Convert integer values to float. Should also check for attributes
2328 that can give decimal values here */
2329 for (i
= 0; i
< nAttributes
; i
++)
2330 pfValues
[i
] = attr
[i
];
2333 HeapFree(GetProcessHeap(), 0, attr
);
2338 /**********************************************************************
2339 * macdrv_wglGetSwapIntervalEXT
2341 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2343 static int macdrv_wglGetSwapIntervalEXT(void)
2345 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2351 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2352 if (err
!= kCGLNoError
)
2354 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2355 err
, CGLErrorString(err
));
2363 /***********************************************************************
2364 * macdrv_wglMakeContextCurrentARB
2366 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2368 * This is not supported directly by OpenGL on the Mac. We emulate it
2369 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2370 * temporarily swap the drawable. This follows the technique used in
2371 * the implementation of Mesa GLX for Apple.
2373 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
2375 struct macdrv_win_data
*data
;
2378 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
2379 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
2383 macdrv_make_context_current(NULL
, NULL
);
2384 NtCurrentTeb()->glContext
= NULL
;
2388 if ((hwnd
= WindowFromDC(draw_hdc
)))
2390 if (!(data
= get_win_data(hwnd
)))
2392 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
2396 if (!data
->pixel_format
)
2398 WARN("no pixel format set\n");
2399 release_win_data(data
);
2400 SetLastError(ERROR_INVALID_HANDLE
);
2403 if (context
->format
!= data
->pixel_format
)
2405 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
2406 release_win_data(data
);
2407 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2411 context
->draw_view
= data
->gl_view
;
2412 context
->draw_pbuffer
= NULL
;
2413 release_win_data(data
);
2417 struct wgl_pbuffer
*pbuffer
;
2419 EnterCriticalSection(&dc_pbuffers_section
);
2420 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
2423 if (context
->format
!= pbuffer
->format
)
2425 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
2426 LeaveCriticalSection(&dc_pbuffers_section
);
2427 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2433 WARN("no window or pbuffer for DC\n");
2434 LeaveCriticalSection(&dc_pbuffers_section
);
2435 SetLastError(ERROR_INVALID_HANDLE
);
2439 context
->draw_view
= NULL
;
2440 context
->draw_pbuffer
= pbuffer
;
2441 LeaveCriticalSection(&dc_pbuffers_section
);
2444 context
->read_view
= NULL
;
2445 context
->read_pbuffer
= NULL
;
2446 if (read_hdc
&& read_hdc
!= draw_hdc
)
2448 if ((hwnd
= WindowFromDC(read_hdc
)))
2450 if ((data
= get_win_data(hwnd
)))
2452 if (data
->gl_view
!= context
->draw_view
)
2453 context
->read_view
= data
->gl_view
;
2454 release_win_data(data
);
2459 EnterCriticalSection(&dc_pbuffers_section
);
2460 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
2461 LeaveCriticalSection(&dc_pbuffers_section
);
2465 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2466 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
2468 make_context_current(context
, FALSE
);
2469 context
->has_been_current
= TRUE
;
2470 NtCurrentTeb()->glContext
= context
;
2476 /**********************************************************************
2477 * macdrv_wglQueryPbufferARB
2479 * WGL_ARB_pbuffer: wglQueryPbufferARB
2481 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
2487 GLenum internalFormat
;
2490 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
2492 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
2493 if (err
!= kCGLNoError
)
2495 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
2496 SetLastError(ERROR_INVALID_HANDLE
);
2502 case WGL_PBUFFER_WIDTH_ARB
:
2505 case WGL_PBUFFER_HEIGHT_ARB
:
2508 case WGL_PBUFFER_LOST_ARB
:
2509 /* Mac PBuffers can't be lost */
2510 *piValue
= GL_FALSE
;
2512 case WGL_TEXTURE_FORMAT_ARB
:
2513 if (pbuffer
->no_texture
)
2514 *piValue
= WGL_NO_TEXTURE_ARB
;
2515 else switch (internalFormat
)
2518 *piValue
= WGL_TEXTURE_RGBA_ARB
;
2522 *piValue
= WGL_TEXTURE_RGB_ARB
;
2526 case WGL_TEXTURE_TARGET_ARB
:
2527 if (pbuffer
->no_texture
)
2528 *piValue
= WGL_NO_TEXTURE_ARB
;
2529 else switch (target
)
2531 case GL_TEXTURE_CUBE_MAP
:
2532 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
2535 *piValue
= WGL_TEXTURE_2D_ARB
;
2537 case GL_TEXTURE_RECTANGLE
:
2539 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
2543 case WGL_MIPMAP_TEXTURE_ARB
:
2544 *piValue
= (pbuffer
->max_level
> 0);
2546 case WGL_MIPMAP_LEVEL_ARB
:
2547 *piValue
= pbuffer
->level
;
2549 case WGL_CUBE_MAP_FACE_ARB
:
2550 switch (pbuffer
->face
)
2552 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
2554 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
2556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
2557 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
2559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
2560 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
2562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
2563 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
2565 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
2566 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
2568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
2569 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
2574 WARN("invalid attribute 0x%x\n", iAttribute
);
2575 SetLastError(ERROR_INVALID_DATA
);
2583 /**********************************************************************
2584 * macdrv_wglReleasePbufferDCARB
2586 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2588 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
2590 struct wgl_pbuffer
*prev
;
2592 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
2594 EnterCriticalSection(&dc_pbuffers_section
);
2596 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2599 if (prev
!= pbuffer
)
2600 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
2601 CGLReleasePBuffer(prev
->pbuffer
);
2602 HeapFree(GetProcessHeap(), 0, prev
);
2603 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
2607 LeaveCriticalSection(&dc_pbuffers_section
);
2609 return hdc
&& DeleteDC(hdc
);
2613 /**********************************************************************
2614 * macdrv_wglReleaseTexImageARB
2616 * WGL_ARB_render_texture: wglReleaseTexImageARB
2618 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2620 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2623 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
2625 if (pbuffer
->no_texture
)
2627 SetLastError(ERROR_INVALID_OPERATION
);
2631 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
2632 if (err
!= kCGLNoError
)
2634 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2635 SetLastError(ERROR_INVALID_OPERATION
);
2643 /**********************************************************************
2644 * macdrv_wglSetPbufferAttribARB
2646 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2648 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
2650 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2652 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
2654 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2656 int attr
= piAttribList
[0];
2657 int value
= piAttribList
[1];
2660 case WGL_MIPMAP_LEVEL_ARB
:
2661 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
2662 pbuffer
->level
= value
;
2664 case WGL_CUBE_MAP_FACE_ARB
:
2667 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
2668 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2669 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2671 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
2672 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2673 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
2675 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
2676 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2677 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
2679 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
2680 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2681 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
2683 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
2684 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2685 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
2687 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
2688 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2689 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
2692 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
2693 SetLastError(ERROR_INVALID_DATA
);
2698 WARN("invalide attribute 0x%x\n", attr
);
2699 SetLastError(ERROR_INVALID_DATA
);
2704 if (context
&& context
->draw_pbuffer
== pbuffer
)
2705 make_context_current(context
, FALSE
);
2711 /**********************************************************************
2712 * macdrv_wglSetPixelFormatWINE
2714 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2716 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
2718 return set_pixel_format(hdc
, fmt
, TRUE
);
2722 /**********************************************************************
2723 * macdrv_wglSwapIntervalEXT
2725 * WGL_EXT_swap_control: wglSwapIntervalEXT
2727 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
2729 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2733 TRACE("interval %d\n", interval
);
2737 SetLastError(ERROR_INVALID_DATA
);
2745 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2746 if (err
!= kCGLNoError
)
2748 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2749 err
, CGLErrorString(err
));
2750 SetLastError(ERROR_GEN_FAILURE
);
2758 static void register_extension(const char *ext
)
2760 if (gl_info
.wglExtensions
[0])
2761 strcat(gl_info
.wglExtensions
, " ");
2762 strcat(gl_info
.wglExtensions
, ext
);
2764 TRACE("'%s'\n", ext
);
2767 static void load_extensions(void)
2772 register_extension("WGL_ARB_extensions_string");
2773 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
2775 register_extension("WGL_ARB_make_current_read");
2776 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
2777 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
2779 register_extension("WGL_ARB_pixel_format");
2780 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
2781 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
2782 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
2784 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
2786 register_extension("WGL_ARB_pixel_format_float");
2787 register_extension("WGL_ATI_pixel_format_float");
2790 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
2791 register_extension("WGL_ARB_multisample");
2793 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
2794 register_extension("WGL_ARB_framebuffer_sRGB");
2796 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
2798 register_extension("WGL_ARB_pbuffer");
2799 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
2800 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
2801 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
2802 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
2803 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
2805 register_extension("WGL_ARB_render_texture");
2806 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
2807 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
2808 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
2810 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
2811 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
2812 register_extension("WGL_NV_render_texture_rectangle");
2816 WGL_ARB_create_context: wglCreateContextAttribsARB
2817 WGL_ARB_create_context_profile
2823 register_extension("WGL_EXT_extensions_string");
2824 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
2826 register_extension("WGL_EXT_swap_control");
2827 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
2828 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
2830 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
2831 check for either, so register them separately. */
2832 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
2833 register_extension("WGL_EXT_framebuffer_sRGB");
2835 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
2836 register_extension("WGL_EXT_pixel_format_packed_float");
2839 * WINE-specific WGL Extensions
2842 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
2843 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
2845 register_extension("WGL_WINE_pixel_format_passthrough");
2846 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
2850 static BOOL
init_opengl(void)
2852 static int init_done
;
2856 if (init_done
) return (opengl_handle
!= NULL
);
2861 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
2864 WARN("CFDictionaryCreateMutable failed\n");
2868 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
2871 ERR("Failed to load OpenGL: %s\n", buffer
);
2872 ERR("OpenGL support is disabled.\n");
2876 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
2878 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
2880 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
2885 /* redirect some standard OpenGL functions */
2886 #define REDIRECT(func) \
2887 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
2888 REDIRECT(glCopyPixels
);
2889 REDIRECT(glReadPixels
);
2890 REDIRECT(glViewport
);
2893 /* redirect some OpenGL extension functions */
2894 #define REDIRECT(func) \
2895 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
2896 REDIRECT(glCopyColorTable
);
2899 if (!init_gl_info())
2903 if (!init_pixel_formats())
2909 wine_dlclose(opengl_handle
, NULL
, 0);
2910 opengl_handle
= NULL
;
2915 /***********************************************************************
2918 * Synchronize the Mac GL view position with the Windows child window
2921 void sync_gl_view(struct macdrv_win_data
*data
)
2925 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
2927 if (!data
->gl_view
) return;
2929 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
2931 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
2932 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
2933 data
->gl_rect
= rect
;
2938 static int get_dc_pixel_format(HDC hdc
)
2943 if ((hwnd
= WindowFromDC(hdc
)))
2945 struct macdrv_win_data
*data
;
2947 if (!(data
= get_win_data(hwnd
)))
2949 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
2953 format
= data
->pixel_format
;
2954 release_win_data(data
);
2958 struct wgl_pbuffer
*pbuffer
;
2960 EnterCriticalSection(&dc_pbuffers_section
);
2961 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2963 format
= pbuffer
->format
;
2966 WARN("no window or pbuffer for DC %p\n", hdc
);
2969 LeaveCriticalSection(&dc_pbuffers_section
);
2976 /**********************************************************************
2979 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
)
2981 const pixel_format
*pf
;
2982 CGLPixelFormatAttribute attribs
[64];
2984 CGLPixelFormatObj pix
;
2985 GLint virtualScreens
;
2989 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
2992 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
2993 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2997 attribs
[n
++] = kCGLPFAMinimumPolicy
;
2998 attribs
[n
++] = kCGLPFAClosestPolicy
;
3000 if (pf
->accelerated
)
3002 attribs
[n
++] = kCGLPFAAccelerated
;
3003 attribs
[n
++] = kCGLPFANoRecovery
;
3007 attribs
[n
++] = kCGLPFARendererID
;
3008 attribs
[n
++] = kCGLRendererGenericFloatID
;
3011 if (pf
->double_buffer
)
3012 attribs
[n
++] = kCGLPFADoubleBuffer
;
3014 attribs
[n
++] = kCGLPFAAuxBuffers
;
3015 attribs
[n
++] = pf
->aux_buffers
;
3017 attribs
[n
++] = kCGLPFAColorSize
;
3018 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
3019 attribs
[n
++] = kCGLPFAAlphaSize
;
3020 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
3021 if (color_modes
[pf
->color_mode
].is_float
)
3022 attribs
[n
++] = kCGLPFAColorFloat
;
3024 attribs
[n
++] = kCGLPFADepthSize
;
3025 attribs
[n
++] = pf
->depth_bits
;
3027 attribs
[n
++] = kCGLPFAStencilSize
;
3028 attribs
[n
++] = pf
->stencil_bits
;
3031 attribs
[n
++] = kCGLPFAStereo
;
3035 attribs
[n
++] = kCGLPFAAccumSize
;
3036 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3040 attribs
[n
++] = kCGLPFAWindow
;
3042 attribs
[n
++] = kCGLPFAPBuffer
;
3044 if (pf
->sample_buffers
&& pf
->samples
)
3046 attribs
[n
++] = kCGLPFASampleBuffers
;
3047 attribs
[n
++] = pf
->sample_buffers
;
3048 attribs
[n
++] = kCGLPFASamples
;
3049 attribs
[n
++] = pf
->samples
;
3052 if (pf
->backing_store
)
3053 attribs
[n
++] = kCGLPFABackingStore
;
3057 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
3058 if (err
!= kCGLNoError
|| !pix
)
3060 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
3064 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
3065 CGLReleasePixelFormat(pix
);
3066 if (err
!= kCGLNoError
|| !context
->cglcontext
)
3068 context
->cglcontext
= NULL
;
3069 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
3073 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3074 a context is 1. CGL contexts default to 0, so we need to set it. */
3076 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&swap_interval
);
3077 if (err
!= kCGLNoError
)
3078 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err
, CGLErrorString(err
));
3080 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
3081 CGLReleaseContext(context
->cglcontext
);
3082 if (!context
->context
)
3084 WARN("macdrv_create_opengl_context() failed\n");
3088 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3094 /**********************************************************************
3095 * macdrv_wglDescribePixelFormat
3097 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3099 int ret
= nb_formats
;
3100 const pixel_format
*pf
;
3101 const struct color_mode
*mode
;
3103 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3105 if (fmt
<= 0 || fmt
> ret
) return ret
;
3106 if (size
< sizeof(*descr
)) return 0;
3108 pf
= &pixel_formats
[fmt
- 1];
3110 memset(descr
, 0, sizeof(*descr
));
3111 descr
->nSize
= sizeof(*descr
);
3112 descr
->nVersion
= 1;
3114 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3115 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3116 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3117 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3118 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3119 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3121 descr
->iPixelType
= PFD_TYPE_RGBA
;
3123 mode
= &color_modes
[pf
->color_mode
];
3124 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3125 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3126 R8G8B8A0 pixel format). If an app depends on that and expects that
3127 cColorBits >= 32 for such a pixel format, we need to accomodate that. */
3128 if (mode
->alpha_bits
)
3129 descr
->cColorBits
= mode
->color_bits
;
3131 descr
->cColorBits
= mode
->bits_per_pixel
;
3132 descr
->cRedBits
= mode
->red_bits
;
3133 descr
->cRedShift
= mode
->red_shift
;
3134 descr
->cGreenBits
= mode
->green_bits
;
3135 descr
->cGreenShift
= mode
->green_shift
;
3136 descr
->cBlueBits
= mode
->blue_bits
;
3137 descr
->cBlueShift
= mode
->blue_shift
;
3138 descr
->cAlphaBits
= mode
->alpha_bits
;
3139 descr
->cAlphaShift
= mode
->alpha_shift
;
3143 mode
= &color_modes
[pf
->accum_mode
- 1];
3144 descr
->cAccumBits
= mode
->color_bits
;
3145 descr
->cAccumRedBits
= mode
->red_bits
;
3146 descr
->cAccumGreenBits
= mode
->green_bits
;
3147 descr
->cAccumBlueBits
= mode
->blue_bits
;
3148 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3151 descr
->cDepthBits
= pf
->depth_bits
;
3152 descr
->cStencilBits
= pf
->stencil_bits
;
3153 descr
->cAuxBuffers
= pf
->aux_buffers
;
3154 descr
->iLayerType
= PFD_MAIN_PLANE
;
3158 /***********************************************************************
3159 * macdrv_wglCopyContext
3161 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3165 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3167 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3168 if (err
!= kCGLNoError
)
3169 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3170 return (err
== kCGLNoError
);
3173 /***********************************************************************
3174 * macdrv_wglCreateContext
3176 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3179 struct wgl_context
*context
;
3181 TRACE("hdc %p\n", hdc
);
3183 format
= get_dc_pixel_format(hdc
);
3185 if (!is_valid_pixel_format(format
))
3187 ERR("Invalid pixel format %d, expect problems!\n", format
);
3188 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3192 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
3194 context
->format
= format
;
3195 if (!create_context(context
, NULL
))
3197 HeapFree(GetProcessHeap(), 0, context
);
3204 /***********************************************************************
3205 * macdrv_wglDeleteContext
3207 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3209 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3210 macdrv_dispose_opengl_context(context
->context
);
3211 HeapFree(GetProcessHeap(), 0, context
);
3214 /***********************************************************************
3215 * macdrv_wglGetPixelFormat
3217 static int macdrv_wglGetPixelFormat(HDC hdc
)
3221 format
= get_dc_pixel_format(hdc
);
3223 if (!is_valid_pixel_format(format
)) /* not set yet */
3225 else if (!is_displayable_pixel_format(format
))
3227 /* Non-displayable formats can't be used with traditional WGL calls.
3228 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3232 TRACE(" hdc %p -> %d\n", hdc
, format
);
3236 /***********************************************************************
3237 * macdrv_wglGetProcAddress
3239 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3243 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3244 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3250 if (dladdr(ret
, &info
))
3251 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3253 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3257 WARN("failed to find proc %s\n", debugstr_a(proc
));
3261 /***********************************************************************
3262 * macdrv_wglMakeCurrent
3264 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3266 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3267 (context
? context
->cglcontext
: NULL
));
3269 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3272 /**********************************************************************
3273 * macdrv_wglSetPixelFormat
3275 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3277 return set_pixel_format(hdc
, fmt
, FALSE
);
3280 /***********************************************************************
3281 * macdrv_wglShareLists
3283 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3285 macdrv_opengl_context saved_context
;
3286 CGLContextObj saved_cglcontext
;
3288 TRACE("org %p dest %p\n", org
, dest
);
3290 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3291 * at context creation time but in case of WGL it is done using wglShareLists.
3293 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3294 * and when a program requests sharing we recreate the destination context if it hasn't been made
3295 * current or when it hasn't shared display lists before.
3298 if (dest
->has_been_current
)
3300 WARN("could not share display lists, the destination context has been current already\n");
3303 else if (dest
->sharing
)
3305 WARN("could not share display lists because dest has already shared lists before\n");
3309 /* Re-create the Mac context and share display lists */
3310 saved_context
= dest
->context
;
3311 saved_cglcontext
= dest
->cglcontext
;
3312 dest
->context
= NULL
;
3313 dest
->cglcontext
= NULL
;
3314 if (!create_context(dest
, org
->cglcontext
))
3316 dest
->context
= saved_context
;
3317 dest
->cglcontext
= saved_cglcontext
;
3321 /* Implicitly disposes of saved_cglcontext. */
3322 macdrv_dispose_opengl_context(saved_context
);
3324 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3325 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3327 org
->sharing
= TRUE
;
3328 dest
->sharing
= TRUE
;
3333 /**********************************************************************
3334 * macdrv_wglSwapBuffers
3336 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3338 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3340 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3341 (context
? context
->cglcontext
: NULL
));
3345 SetLastError(ERROR_INVALID_HANDLE
);
3349 macdrv_flush_opengl_context(context
->context
);
3353 static struct opengl_funcs opengl_funcs
=
3356 macdrv_wglCopyContext
, /* p_wglCopyContext */
3357 macdrv_wglCreateContext
, /* p_wglCreateContext */
3358 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3359 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3360 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3361 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3362 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3363 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3364 macdrv_wglShareLists
, /* p_wglShareLists */
3365 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3369 /**********************************************************************
3370 * macdrv_wine_get_wgl_driver
3372 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3374 if (version
!= WINE_WGL_DRIVER_VERSION
)
3376 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3380 if (!init_opengl()) return (void *)-1;
3382 return &opengl_funcs
;