winemac: Set the ordering of color modes explicitly to reduce chance of picking an...
[wine/multimedia.git] / dlls / winemac.drv / opengl.c
blob8a29d897d0a21e8c4ba86efe155010ae3826d6f8
1 /*
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
22 #include "config.h"
23 #include "wine/port.h"
25 #include "macdrv.h"
27 #include "winuser.h"
28 #include "winternl.h"
29 #include "wine/library.h"
30 #include "wine/debug.h"
31 #include "wine/wgl.h"
32 #include "wine/wgl_driver.h"
33 #include "wine/wglext.h"
35 #define __gl_h_
36 #define __gltypes_h_
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
40 #include <dlfcn.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
45 struct gl_info {
46 char *glVersion;
47 char *glExtensions;
49 char wglExtensions[4096];
51 GLint max_viewport_dims[2];
54 static struct gl_info gl_info;
57 struct wgl_context
59 HDC hdc;
60 int format;
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;
68 BOOL sharing;
72 struct wgl_pbuffer
74 CGLPBufferObj pbuffer;
75 int format;
76 BOOL no_texture;
77 int max_level;
78 GLint level;
79 GLenum face;
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 };
98 #undef USE_GL_FUNC
101 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
102 GLsizei width);
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);
109 struct color_mode {
110 GLint mode;
111 int bits_per_pixel;
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;
117 BOOL is_float;
118 int color_ordering;
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
136 components.
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 {
171 GLint mode;
172 int bits;
173 } depth_stencil_modes[] = {
174 { kCGL0Bit, 0 },
175 { kCGL1Bit, 1 },
176 { kCGL2Bit, 2 },
177 { kCGL3Bit, 3 },
178 { kCGL4Bit, 4 },
179 { kCGL5Bit, 5 },
180 { kCGL6Bit, 6 },
181 { kCGL8Bit, 8 },
182 { kCGL10Bit, 10 },
183 { kCGL12Bit, 12 },
184 { kCGL16Bit, 16 },
185 { kCGL24Bit, 24 },
186 { kCGL32Bit, 32 },
187 { kCGL48Bit, 48 },
188 { kCGL64Bit, 64 },
189 { kCGL96Bit, 96 },
190 { kCGL128Bit, 128 },
194 typedef struct {
195 GLint renderer_id;
196 GLint buffer_modes;
197 GLint color_modes;
198 GLint accum_modes;
199 GLint depth_modes;
200 GLint stencil_modes;
201 GLint max_aux_buffers;
202 GLint max_sample_buffers;
203 GLint max_samples;
204 BOOL offscreen;
205 BOOL accelerated;
206 BOOL backing_store;
207 BOOL window;
208 BOOL online;
209 } renderer_properties;
212 typedef struct {
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;
226 } pixel_format;
229 typedef union
231 pixel_format format;
232 UInt64 code;
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)
255 GLint value;
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)
305 int i;
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)
321 TRACE(", Float");
322 TRACE("\n");
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);
332 TRACE("}\n");
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);
340 TRACE("}\n");
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);
348 TRACE("}\n");
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;
365 pfc.code = 0;
366 pfc.format = *format;
367 return pfc.code;
371 static inline pixel_format pixel_format_for_code(UInt64 code)
373 pixel_format_or_code pfc;
375 pfc.code = code;
376 return pfc.format;
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",
383 pf->window,
384 pf->pbuffer,
385 pf->accelerated,
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,
389 pf->depth_bits,
390 pf->stencil_bits,
391 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
392 pf->aux_buffers,
393 pf->backing_store,
394 pf->double_buffer,
395 pf->stereo,
396 pf->sample_buffers,
397 pf->samples,
398 code_for_pixel_format(pf));
402 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
404 int best = -1;
405 int i;
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 */
415 best = i;
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)
423 best = i;
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 */
428 best = i;
432 if (best < 0)
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)
438 return i;
442 return best;
446 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
448 int best = -1;
449 int i;
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. */
457 if (best < 0)
458 best = i;
459 else if (color_modes[i].color_bits < color_modes[best].color_bits)
460 best = i;
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)
464 best = i;
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)
467 best = i;
472 if (best < 0)
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)
478 return i;
482 return best;
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;
502 if (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++)
511 unsigned int aux;
513 n = n_stack[n_stack_idx];
515 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
516 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
517 continue;
519 if (double_buffer)
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;
534 attribs[n++] = aux;
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))
545 continue;
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))
563 continue;
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++)
572 unsigned int stereo;
574 n = n_stack[n_stack_idx];
576 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
577 continue;
578 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
579 continue;
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++)
590 int accum_mode;
592 n = n_stack[n_stack_idx];
594 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
595 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
596 continue;
598 if (stereo)
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];
610 if (accum_mode >= 0)
612 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
613 continue;
615 attribs[n++] = kCGLPFAAccumSize;
616 attribs[n++] = color_modes[accum_mode].color_bits;
617 request.accum_mode = accum_mode + 1;
619 else
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;
633 request.window = 1;
635 if (!accelerated || target_pass > 0)
637 attribs[n++] = kCGLPFAPBuffer;
638 request.pbuffer = 1;
640 else
641 request.pbuffer = 0;
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];
654 if (samples > 1)
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;
663 else
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;
673 else
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;
680 CGLError err;
682 n = n_stack[n_stack_idx];
684 if (backing_store)
685 attribs[n++] = kCGLPFABackingStore;
686 request.backing_store = backing_store;
688 attribs[n] = 0;
690 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
691 if (err == kCGLNoError && pix)
693 pixel_format pf;
694 GLint value, color_size, alpha_size, color_float;
695 UInt64 pf_code;
696 CFNumberRef code_object;
697 BOOL dupe;
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)
713 pf.pbuffer = value;
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)
718 pf.samples = value;
719 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
720 pf.stencil_bits = value;
721 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
722 pf.stereo = value;
723 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
724 pf.window = value;
726 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
727 color_size = 0;
728 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
729 alpha_size = 0;
730 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
731 color_float = 0;
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++;
744 else
746 CFSetAddValue(pixel_format_set, code_object);
747 CFArrayAppendValue(pixel_format_array, code_object);
748 new_pixel_formats++;
750 CFRelease(code_object);
752 if (pf_code == code_for_pixel_format(&request))
753 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
754 else
756 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
757 dupe ? " (duplicate)" : "");
760 else
762 failed_pixel_formats++;
763 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
766 tried_pixel_formats++;
769 n_stack_idx--;
772 n_stack_idx--;
775 n_stack_idx--;
778 n_stack_idx--;
781 n_stack_idx--;
784 n_stack_idx--;
787 n_stack_idx--;
790 n_stack_idx--;
793 n_stack_idx--;
796 n_stack_idx--;
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
809 extended attributes
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 */
816 if (!pf.window)
817 return 4;
819 /* non-accelerated a.k.a. software a.k.a. generic */
820 if (!pf.accelerated)
821 return 3;
823 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
824 if (color_modes[pf.color_mode].is_float)
825 return 2;
827 /* accelerated, displayable, no extended attributes */
828 return 1;
832 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
834 CFNumberRef number1 = val1;
835 CFNumberRef number2 = val2;
836 UInt64 code1, code2;
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
893 double buffering. */
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.) */
918 if (pf1.accum_mode)
920 if (pf2.accum_mode)
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;
939 else
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. */
952 if (code1 < code2)
953 return kCFCompareLessThan;
954 if (code1 > code2)
955 return kCFCompareGreaterThan;
956 return kCFCompareEqualTo;
960 static BOOL init_pixel_formats(void)
962 BOOL ret = FALSE;
963 CGLRendererInfoObj renderer_info;
964 GLint rendererCount;
965 CGLError err;
966 CFMutableSetRef pixel_format_set;
967 CFMutableArrayRef pixel_format_array;
968 int i;
969 CFRange range;
971 TRACE("()\n");
973 assert(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
975 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
976 if (err)
978 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
979 return FALSE;
982 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
983 if (!pixel_format_set)
985 WARN("CFSetCreateMutable failed\n");
986 CGLDestroyRendererInfo(renderer_info);
987 return FALSE;
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);
996 return FALSE;
999 for (i = 0; i < rendererCount; i++)
1001 renderer_properties renderer;
1003 get_renderer_properties(renderer_info, i, &renderer);
1004 if (TRACE_ON(wgl))
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));
1017 if (range.length)
1019 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1020 if (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);
1026 UInt64 code;
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);
1036 ret = TRUE;
1038 else
1039 WARN("failed to allocate pixel format list\n");
1041 else
1042 WARN("got no pixel formats\n");
1044 CFRelease(pixel_format_array);
1045 return ret;
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];
1071 return NULL;
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;
1085 CGLError err;
1086 CGLContextObj context;
1087 CGLContextObj old_context = CGLGetCurrentContext();
1088 const char *str;
1090 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1091 if (err != kCGLNoError || !pix)
1093 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1094 return FALSE;
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));
1102 return FALSE;
1105 err = CGLSetCurrentContext(context);
1106 if (err != kCGLNoError)
1108 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1109 CGLReleaseContext(context);
1110 return FALSE;
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);
1128 return TRUE;
1132 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1134 BOOL ret = TRUE;
1135 *rect = data->client_rect;
1137 if (data->cocoa_window)
1139 if (window)
1140 *window = data->cocoa_window;
1141 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1143 else
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)
1151 if (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);
1156 else
1157 ret = FALSE;
1159 release_win_data(top_data);
1162 return ret;
1166 /***********************************************************************
1167 * set_win_format
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");
1178 return FALSE;
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));
1184 if (!data->gl_view)
1186 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1187 return FALSE;
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;
1195 return TRUE;
1199 /**********************************************************************
1200 * set_pixel_format
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);
1209 BOOL ret = FALSE;
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);
1216 return FALSE;
1219 if (!(data = get_win_data(hwnd)))
1221 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1222 return FALSE;
1225 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1227 ret = (data->pixel_format == fmt);
1228 goto done;
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 */);
1233 if (!pf)
1235 ERR("Invalid pixel format: %d\n", fmt);
1236 goto done;
1239 if (!pf->window)
1241 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1242 goto done;
1245 if (!set_win_format(data, fmt))
1247 WARN("Couldn't set format of the window, returning failure\n");
1248 goto done;
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);
1266 ret = TRUE;
1268 done:
1269 release_win_data(data);
1270 if (ret) __wine_set_pixel_format(hwnd, fmt);
1271 return ret;
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;
1284 if (data->gl_view)
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 );
1297 return;
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)
1312 macdrv_view view;
1313 struct wgl_pbuffer *pbuffer;
1315 if (read)
1317 view = context->read_view;
1318 pbuffer = context->read_pbuffer;
1320 else
1322 view = context->draw_view;
1323 pbuffer = context->draw_pbuffer;
1326 if (view || !pbuffer)
1327 macdrv_make_context_current(context->context, view);
1328 else
1330 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1331 pbuffer->level, 0);
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,
1347 GLsizei width)
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 /**********************************************************************
1409 * macdrv_glViewport
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;
1432 GLenum source;
1433 CGLError err;
1435 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1437 if (pbuffer->no_texture)
1439 SetLastError(ERROR_INVALID_OPERATION);
1440 return GL_FALSE;
1443 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1444 opengl_funcs.gl.p_glFlush();
1446 switch (iBuffer)
1448 case WGL_FRONT_LEFT_ARB:
1449 if (pixel_formats[pbuffer->format].stereo)
1450 source = GL_FRONT_LEFT;
1451 else
1452 source = GL_FRONT;
1453 break;
1454 case WGL_FRONT_RIGHT_ARB:
1455 source = GL_FRONT_RIGHT;
1456 break;
1457 case WGL_BACK_LEFT_ARB:
1458 if (pixel_formats[pbuffer->format].stereo)
1459 source = GL_BACK_LEFT;
1460 else
1461 source = GL_BACK;
1462 break;
1463 case WGL_BACK_RIGHT_ARB:
1464 source = GL_BACK_RIGHT;
1465 break;
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;
1471 case WGL_AUX4_ARB:
1472 case WGL_AUX5_ARB:
1473 case WGL_AUX6_ARB:
1474 case WGL_AUX7_ARB:
1475 case WGL_AUX8_ARB:
1476 case WGL_AUX9_ARB:
1477 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1478 SetLastError(ERROR_INVALID_DATA);
1479 return GL_FALSE;
1481 default:
1482 WARN("unknown source buffer 0x%x\n", iBuffer);
1483 SetLastError(ERROR_INVALID_DATA);
1484 return GL_FALSE;
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);
1492 return GL_FALSE;
1495 return GL_TRUE;
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;
1509 const int *iptr;
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;
1512 int float_color;
1513 BOOL srgb;
1514 int i, found = 0;
1516 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1517 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1518 if (pfAttribFList)
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;
1525 float_color = -1;
1526 srgb = FALSE;
1528 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1530 int attr = iptr[0];
1531 int value = iptr[1];
1533 switch (attr)
1535 case WGL_DRAW_TO_WINDOW_ARB:
1536 if (valid.window && (!pf.window != !value)) goto cant_match;
1537 pf.window = (value != 0);
1538 valid.window = 1;
1539 break;
1541 case WGL_DRAW_TO_BITMAP_ARB:
1542 goto cant_match;
1544 case WGL_ACCELERATION_ARB:
1545 if (value == WGL_FULL_ACCELERATION_ARB)
1546 value = 1;
1547 else if (value == WGL_NO_ACCELERATION_ARB)
1548 value = 0;
1549 else
1550 goto cant_match;
1551 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1552 pf.accelerated = value;
1553 valid.accelerated = 1;
1554 break;
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;
1560 break;
1562 case WGL_SWAP_METHOD_ARB:
1563 if (value == WGL_SWAP_COPY_ARB)
1564 value = 1;
1565 else if (value == WGL_SWAP_UNDEFINED_ARB)
1566 value = 0;
1567 else
1568 goto cant_match;
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;
1573 break;
1575 case WGL_NUMBER_OVERLAYS_ARB:
1576 case WGL_NUMBER_UNDERLAYS_ARB:
1577 if (value) goto cant_match;
1578 break;
1580 case WGL_SHARE_DEPTH_ARB:
1581 case WGL_SHARE_STENCIL_ARB:
1582 case WGL_SHARE_ACCUM_ARB:
1583 /* no effect */
1584 break;
1586 case WGL_SUPPORT_GDI_ARB:
1587 if (value) goto cant_match;
1588 break;
1590 case WGL_SUPPORT_OPENGL_ARB:
1591 if (!value) goto cant_match;
1592 break;
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;
1599 break;
1601 case WGL_STEREO_ARB:
1602 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1603 pf.stereo = (value != 0);
1604 valid.stereo = 1;
1605 break;
1607 case WGL_PIXEL_TYPE_ARB:
1608 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1609 value = 1;
1610 else if (value == WGL_TYPE_RGBA_ARB)
1611 value = 0;
1612 else
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. */
1617 goto cant_match;
1619 if (float_color != -1 && float_color != value) goto cant_match;
1620 if (srgb && value) goto cant_match;
1621 float_color = value;
1622 break;
1624 case WGL_COLOR_BITS_ARB:
1625 if (color_bits < value) color_bits = value;
1626 break;
1628 case WGL_RED_BITS_ARB:
1629 if (srgb && value > 8) goto cant_match;
1630 if (red_bits < value) red_bits = value;
1631 break;
1633 case WGL_GREEN_BITS_ARB:
1634 if (srgb && value > 8) goto cant_match;
1635 if (green_bits < value) green_bits = value;
1636 break;
1638 case WGL_BLUE_BITS_ARB:
1639 if (srgb && value > 8) goto cant_match;
1640 if (blue_bits < value) blue_bits = value;
1641 break;
1643 case WGL_ALPHA_BITS_ARB:
1644 if (alpha_bits < value) alpha_bits = value;
1645 break;
1647 case WGL_ACCUM_BITS_ARB:
1648 if (accum_bits < value) accum_bits = value;
1649 break;
1651 case WGL_ACCUM_RED_BITS_ARB:
1652 if (accum_red_bits < value) accum_red_bits = value;
1653 break;
1655 case WGL_ACCUM_GREEN_BITS_ARB:
1656 if (accum_green_bits < value) accum_green_bits = value;
1657 break;
1659 case WGL_ACCUM_BLUE_BITS_ARB:
1660 if (accum_blue_bits < value) accum_blue_bits = value;
1661 break;
1663 case WGL_ACCUM_ALPHA_BITS_ARB:
1664 if (accum_alpha_bits < value) accum_alpha_bits = value;
1665 break;
1667 case WGL_DEPTH_BITS_ARB:
1668 if (value > 255) goto cant_match;
1669 if (pf.depth_bits < value) pf.depth_bits = value;
1670 break;
1672 case WGL_STENCIL_BITS_ARB:
1673 if (value > 255) goto cant_match;
1674 if (pf.stencil_bits < value) pf.stencil_bits = value;
1675 break;
1677 case WGL_AUX_BUFFERS_ARB:
1678 if (value > 7) goto cant_match;
1679 if (pf.aux_buffers < value) pf.aux_buffers = value;
1680 break;
1682 case WGL_SAMPLE_BUFFERS_ARB:
1683 if (value > 1) goto cant_match;
1684 if (pf.sample_buffers < value) pf.sample_buffers = value;
1685 break;
1687 case WGL_SAMPLES_ARB:
1688 if (value > 31) goto cant_match;
1689 if (pf.samples < value) pf.samples = value;
1690 break;
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)
1695 goto cant_match;
1696 srgb = TRUE;
1697 break;
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:
1710 /* ignored */
1711 break;
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);
1720 valid.pbuffer = 1;
1721 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1722 !alpha_bits)
1723 alpha_bits = 1;
1724 break;
1726 default:
1727 WARN("invalid attribute %x\n", iptr[0]);
1728 return GL_FALSE;
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)
1758 continue;
1760 else
1762 if (mode->bits_per_pixel < color_bits)
1763 continue;
1765 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
1766 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
1767 continue;
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))
1770 continue;
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)
1778 continue;
1780 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
1781 continue;
1783 piFormats[found++] = i;
1786 cant_match:
1787 *nNumFormats = found;
1789 return TRUE;
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;
1802 GLenum target = 0;
1803 GLenum internalFormat = 0;
1804 CGLError err;
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);
1813 return NULL;
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];
1824 switch (attr)
1826 case WGL_PBUFFER_LARGEST_ARB:
1827 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
1828 break;
1830 case WGL_TEXTURE_FORMAT_ARB:
1831 switch (value)
1833 case WGL_TEXTURE_RGBA_ARB:
1834 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
1835 internalFormat = GL_RGBA;
1836 break;
1837 case WGL_TEXTURE_RGB_ARB:
1838 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
1839 internalFormat = GL_RGB;
1840 break;
1841 case WGL_NO_TEXTURE_ARB:
1842 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
1843 internalFormat = 0;
1844 break;
1845 default:
1846 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
1847 SetLastError(ERROR_INVALID_DATA);
1848 goto done;
1850 break;
1852 case WGL_TEXTURE_TARGET_ARB:
1853 pbuffer->face = 0;
1854 switch (value)
1856 case WGL_NO_TEXTURE_ARB:
1857 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
1858 target = 0;
1859 break;
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;
1864 break;
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);
1868 goto done;
1869 case WGL_TEXTURE_2D_ARB:
1870 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
1871 target = GL_TEXTURE_2D;
1872 break;
1873 case WGL_TEXTURE_RECTANGLE_NV:
1874 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
1875 target = GL_TEXTURE_RECTANGLE;
1876 break;
1877 default:
1878 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
1879 SetLastError(ERROR_INVALID_DATA);
1880 goto done;
1882 break;
1884 case WGL_MIPMAP_TEXTURE_ARB:
1885 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
1886 pbuffer->max_level = 0;
1887 if (value)
1889 int size = min(iWidth, iHeight) / 2;
1890 while (size)
1892 pbuffer->max_level++;
1893 size /= 2;
1896 break;
1898 default:
1899 WARN("unknown attribute 0x%x\n", attr);
1900 SetLastError(ERROR_INVALID_DATA);
1901 goto done;
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);
1920 else
1921 SetLastError(ERROR_INVALID_DATA);
1924 done:
1925 if (!pbuffer->pbuffer)
1927 HeapFree(GetProcessHeap(), 0, pbuffer);
1928 return NULL;
1931 TRACE(" -> %p\n", pbuffer);
1932 return 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);
1947 return GL_TRUE;
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)
1984 HDC hdc;
1985 struct wgl_pbuffer *prev;
1987 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1988 if (!hdc) return 0;
1990 EnterCriticalSection(&dc_pbuffers_section);
1991 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1992 if (prev)
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);
2001 return 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;
2014 UINT i;
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;
2024 return GL_TRUE;
2027 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2028 if (!pf)
2030 WARN("invalid pixel format %d\n", iPixelFormat);
2031 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2032 return GL_FALSE;
2035 for (i = 0; i < nAttributes; ++i)
2037 switch (piAttributes[i])
2039 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2040 piValues[i] = nb_formats;
2041 break;
2043 case WGL_DRAW_TO_WINDOW_ARB:
2044 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2045 break;
2047 case WGL_DRAW_TO_BITMAP_ARB:
2048 piValues[i] = GL_FALSE;
2049 break;
2051 case WGL_ACCELERATION_ARB:
2052 if (iLayerPlane) goto invalid_layer;
2053 if (pf->accelerated)
2054 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2055 else
2056 piValues[i] = WGL_NO_ACCELERATION_ARB;
2057 break;
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;
2063 break;
2065 case WGL_SWAP_METHOD_ARB:
2066 if (pf->double_buffer && pf->backing_store)
2067 piValues[i] = WGL_SWAP_COPY_ARB;
2068 else
2069 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2070 break;
2072 case WGL_NUMBER_OVERLAYS_ARB:
2073 case WGL_NUMBER_UNDERLAYS_ARB:
2074 piValues[i] = 0;
2075 break;
2077 case WGL_TRANSPARENT_ARB:
2078 if (iLayerPlane) goto invalid_layer;
2079 piValues[i] = GL_FALSE;
2080 break;
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;
2088 piValues[i] = 0;
2089 break;
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;
2096 break;
2098 case WGL_SUPPORT_GDI_ARB:
2099 if (iLayerPlane) goto invalid_layer;
2100 piValues[i] = GL_FALSE;
2101 break;
2103 case WGL_SUPPORT_OPENGL_ARB:
2104 if (iLayerPlane) goto invalid_layer;
2105 piValues[i] = GL_TRUE;
2106 break;
2108 case WGL_DOUBLE_BUFFER_ARB:
2109 if (iLayerPlane) goto invalid_layer;
2110 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2111 break;
2113 case WGL_STEREO_ARB:
2114 if (iLayerPlane) goto invalid_layer;
2115 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2116 break;
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;
2122 else
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. */
2128 break;
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;
2139 else
2140 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2141 break;
2143 case WGL_RED_BITS_ARB:
2144 if (iLayerPlane) goto invalid_layer;
2145 piValues[i] = color_modes[pf->color_mode].red_bits;
2146 break;
2148 case WGL_RED_SHIFT_ARB:
2149 if (iLayerPlane) goto invalid_layer;
2150 piValues[i] = color_modes[pf->color_mode].red_shift;
2151 break;
2153 case WGL_GREEN_BITS_ARB:
2154 if (iLayerPlane) goto invalid_layer;
2155 piValues[i] = color_modes[pf->color_mode].green_bits;
2156 break;
2158 case WGL_GREEN_SHIFT_ARB:
2159 if (iLayerPlane) goto invalid_layer;
2160 piValues[i] = color_modes[pf->color_mode].green_shift;
2161 break;
2163 case WGL_BLUE_BITS_ARB:
2164 if (iLayerPlane) goto invalid_layer;
2165 piValues[i] = color_modes[pf->color_mode].blue_bits;
2166 break;
2168 case WGL_BLUE_SHIFT_ARB:
2169 if (iLayerPlane) goto invalid_layer;
2170 piValues[i] = color_modes[pf->color_mode].blue_shift;
2171 break;
2173 case WGL_ALPHA_BITS_ARB:
2174 if (iLayerPlane) goto invalid_layer;
2175 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2176 break;
2178 case WGL_ALPHA_SHIFT_ARB:
2179 if (iLayerPlane) goto invalid_layer;
2180 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2181 break;
2183 case WGL_ACCUM_BITS_ARB:
2184 if (iLayerPlane) goto invalid_layer;
2185 if (pf->accum_mode)
2186 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2187 else
2188 piValues[i] = 0;
2189 break;
2191 case WGL_ACCUM_RED_BITS_ARB:
2192 if (iLayerPlane) goto invalid_layer;
2193 if (pf->accum_mode)
2194 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2195 else
2196 piValues[i] = 0;
2197 break;
2199 case WGL_ACCUM_GREEN_BITS_ARB:
2200 if (iLayerPlane) goto invalid_layer;
2201 if (pf->accum_mode)
2202 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2203 else
2204 piValues[i] = 0;
2205 break;
2207 case WGL_ACCUM_BLUE_BITS_ARB:
2208 if (iLayerPlane) goto invalid_layer;
2209 if (pf->accum_mode)
2210 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2211 else
2212 piValues[i] = 0;
2213 break;
2215 case WGL_ACCUM_ALPHA_BITS_ARB:
2216 if (iLayerPlane) goto invalid_layer;
2217 if (pf->accum_mode)
2218 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2219 else
2220 piValues[i] = 0;
2221 break;
2223 case WGL_DEPTH_BITS_ARB:
2224 if (iLayerPlane) goto invalid_layer;
2225 piValues[i] = pf->depth_bits;
2226 break;
2228 case WGL_STENCIL_BITS_ARB:
2229 if (iLayerPlane) goto invalid_layer;
2230 piValues[i] = pf->stencil_bits;
2231 break;
2233 case WGL_AUX_BUFFERS_ARB:
2234 if (iLayerPlane) goto invalid_layer;
2235 piValues[i] = pf->aux_buffers;
2236 break;
2238 case WGL_SAMPLE_BUFFERS_ARB:
2239 if (iLayerPlane) goto invalid_layer;
2240 piValues[i] = pf->sample_buffers;
2241 break;
2243 case WGL_SAMPLES_ARB:
2244 if (iLayerPlane) goto invalid_layer;
2245 piValues[i] = pf->samples;
2246 break;
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;
2256 else
2257 piValues[i] = GL_FALSE;
2258 break;
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;
2264 break;
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;
2269 break;
2271 case WGL_MAX_PBUFFER_WIDTH_ARB:
2272 piValues[i] = gl_info.max_viewport_dims[0];
2273 break;
2275 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2276 piValues[i] = gl_info.max_viewport_dims[1];
2277 break;
2279 case WGL_MAX_PBUFFER_PIXELS_ARB:
2280 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2281 break;
2283 default:
2284 WARN("invalid attribute %x\n", piAttributes[i]);
2285 return GL_FALSE;
2288 TRACE("piAttributes[%d] (%x) -> %x\n", i, piAttributes[i], piValues[i]);
2291 return GL_TRUE;
2293 invalid_layer:
2294 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2295 return GL_FALSE;
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)
2307 int *attr;
2308 int ret;
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));
2315 if (!attr)
2317 ERR("couldn't allocate %d array\n", nAttributes);
2318 return GL_FALSE;
2321 /* Piggy-back on wglGetPixelFormatAttribivARB */
2322 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2323 if (ret)
2325 UINT i;
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);
2334 return ret;
2338 /**********************************************************************
2339 * macdrv_wglGetSwapIntervalEXT
2341 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2343 static int macdrv_wglGetSwapIntervalEXT(void)
2345 struct wgl_context *context = NtCurrentTeb()->glContext;
2346 long value;
2347 CGLError err;
2349 TRACE("\n");
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));
2356 value = 1;
2359 return value;
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;
2376 HWND hwnd;
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));
2381 if (!context)
2383 macdrv_make_context_current(NULL, NULL);
2384 NtCurrentTeb()->glContext = NULL;
2385 return TRUE;
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);
2393 return FALSE;
2396 if (!data->pixel_format)
2398 WARN("no pixel format set\n");
2399 release_win_data(data);
2400 SetLastError(ERROR_INVALID_HANDLE);
2401 return FALSE;
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);
2408 return FALSE;
2411 context->draw_view = data->gl_view;
2412 context->draw_pbuffer = NULL;
2413 release_win_data(data);
2415 else
2417 struct wgl_pbuffer *pbuffer;
2419 EnterCriticalSection(&dc_pbuffers_section);
2420 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2421 if (pbuffer)
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);
2428 return FALSE;
2431 else
2433 WARN("no window or pbuffer for DC\n");
2434 LeaveCriticalSection(&dc_pbuffers_section);
2435 SetLastError(ERROR_INVALID_HANDLE);
2436 return FALSE;
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);
2457 else
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;
2472 return TRUE;
2476 /**********************************************************************
2477 * macdrv_wglQueryPbufferARB
2479 * WGL_ARB_pbuffer: wglQueryPbufferARB
2481 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2483 CGLError err;
2484 GLsizei width;
2485 GLsizei height;
2486 GLenum target;
2487 GLenum internalFormat;
2488 GLint mipmap;
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);
2497 return GL_FALSE;
2500 switch (iAttribute)
2502 case WGL_PBUFFER_WIDTH_ARB:
2503 *piValue = width;
2504 break;
2505 case WGL_PBUFFER_HEIGHT_ARB:
2506 *piValue = height;
2507 break;
2508 case WGL_PBUFFER_LOST_ARB:
2509 /* Mac PBuffers can't be lost */
2510 *piValue = GL_FALSE;
2511 break;
2512 case WGL_TEXTURE_FORMAT_ARB:
2513 if (pbuffer->no_texture)
2514 *piValue = WGL_NO_TEXTURE_ARB;
2515 else switch (internalFormat)
2517 case GL_RGBA:
2518 *piValue = WGL_TEXTURE_RGBA_ARB;
2519 break;
2520 case GL_RGB:
2521 default:
2522 *piValue = WGL_TEXTURE_RGB_ARB;
2523 break;
2525 break;
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;
2533 break;
2534 case GL_TEXTURE_2D:
2535 *piValue = WGL_TEXTURE_2D_ARB;
2536 break;
2537 case GL_TEXTURE_RECTANGLE:
2538 default:
2539 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2540 break;
2542 break;
2543 case WGL_MIPMAP_TEXTURE_ARB:
2544 *piValue = (pbuffer->max_level > 0);
2545 break;
2546 case WGL_MIPMAP_LEVEL_ARB:
2547 *piValue = pbuffer->level;
2548 break;
2549 case WGL_CUBE_MAP_FACE_ARB:
2550 switch (pbuffer->face)
2552 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2553 default:
2554 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2555 break;
2556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2557 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2558 break;
2559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2560 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2561 break;
2562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2563 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2564 break;
2565 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2566 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2567 break;
2568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2569 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2570 break;
2572 break;
2573 default:
2574 WARN("invalid attribute 0x%x\n", iAttribute);
2575 SetLastError(ERROR_INVALID_DATA);
2576 return GL_FALSE;
2579 return GL_TRUE;
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);
2597 if (prev)
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);
2605 else hdc = 0;
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;
2621 CGLError err;
2623 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2625 if (pbuffer->no_texture)
2627 SetLastError(ERROR_INVALID_OPERATION);
2628 return GL_FALSE;
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);
2636 return GL_FALSE;
2639 return GL_TRUE;
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];
2658 switch (attr)
2660 case WGL_MIPMAP_LEVEL_ARB:
2661 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2662 pbuffer->level = value;
2663 break;
2664 case WGL_CUBE_MAP_FACE_ARB:
2665 switch (value)
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;
2670 break;
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;
2674 break;
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;
2678 break;
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;
2682 break;
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;
2686 break;
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;
2690 break;
2691 default:
2692 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
2693 SetLastError(ERROR_INVALID_DATA);
2694 return GL_FALSE;
2696 break;
2697 default:
2698 WARN("invalide attribute 0x%x\n", attr);
2699 SetLastError(ERROR_INVALID_DATA);
2700 return GL_FALSE;
2704 if (context && context->draw_pbuffer == pbuffer)
2705 make_context_current(context, FALSE);
2707 return GL_TRUE;
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;
2730 long value;
2731 CGLError err;
2733 TRACE("interval %d\n", interval);
2735 if (interval < 0)
2737 SetLastError(ERROR_INVALID_DATA);
2738 return FALSE;
2741 if (interval > 1)
2742 interval = 1;
2744 value = interval;
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);
2751 return FALSE;
2754 return TRUE;
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)
2770 * ARB Extensions
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");
2815 /* TODO:
2816 WGL_ARB_create_context: wglCreateContextAttribsARB
2817 WGL_ARB_create_context_profile
2821 * EXT Extensions
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;
2853 unsigned int i;
2854 char buffer[200];
2856 if (init_done) return (opengl_handle != NULL);
2857 init_done = 1;
2859 TRACE("()\n");
2861 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
2862 if (!dc_pbuffers)
2864 WARN("CFDictionaryCreateMutable failed\n");
2865 return FALSE;
2868 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
2869 if (!opengl_handle)
2871 ERR("Failed to load OpenGL: %s\n", buffer);
2872 ERR("OpenGL support is disabled.\n");
2873 return FALSE;
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]);
2881 goto failed;
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);
2891 #undef REDIRECT
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);
2897 #undef REDIRECT
2899 if (!init_gl_info())
2900 goto failed;
2902 load_extensions();
2903 if (!init_pixel_formats())
2904 goto failed;
2906 return TRUE;
2908 failed:
2909 wine_dlclose(opengl_handle, NULL, 0);
2910 opengl_handle = NULL;
2911 return FALSE;
2915 /***********************************************************************
2916 * sync_gl_view
2918 * Synchronize the Mac GL view position with the Windows child window
2919 * position.
2921 void sync_gl_view(struct macdrv_win_data *data)
2923 RECT rect;
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)
2940 int format;
2941 HWND hwnd;
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);
2950 return 0;
2953 format = data->pixel_format;
2954 release_win_data(data);
2956 else
2958 struct wgl_pbuffer *pbuffer;
2960 EnterCriticalSection(&dc_pbuffers_section);
2961 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2962 if (pbuffer)
2963 format = pbuffer->format;
2964 else
2966 WARN("no window or pbuffer for DC %p\n", hdc);
2967 format = 0;
2969 LeaveCriticalSection(&dc_pbuffers_section);
2972 return format;
2976 /**********************************************************************
2977 * create_context
2979 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
2981 const pixel_format *pf;
2982 CGLPixelFormatAttribute attribs[64];
2983 int n = 0;
2984 CGLPixelFormatObj pix;
2985 GLint virtualScreens;
2986 CGLError err;
2987 long swap_interval;
2989 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
2990 if (!pf)
2992 ERR("Invalid pixel format %d, expect problems!\n", context->format);
2993 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2994 return FALSE;
2997 attribs[n++] = kCGLPFAMinimumPolicy;
2998 attribs[n++] = kCGLPFAClosestPolicy;
3000 if (pf->accelerated)
3002 attribs[n++] = kCGLPFAAccelerated;
3003 attribs[n++] = kCGLPFANoRecovery;
3005 else
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;
3030 if (pf->stereo)
3031 attribs[n++] = kCGLPFAStereo;
3033 if (pf->accum_mode)
3035 attribs[n++] = kCGLPFAAccumSize;
3036 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3039 if (pf->window)
3040 attribs[n++] = kCGLPFAWindow;
3041 if (pf->pbuffer)
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;
3055 attribs[n] = 0;
3057 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3058 if (err != kCGLNoError || !pix)
3060 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3061 return FALSE;
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));
3070 return FALSE;
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. */
3075 swap_interval = 1;
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");
3085 return FALSE;
3088 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3090 return TRUE;
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;
3130 else
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;
3141 if (pf->accum_mode)
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;
3155 return ret;
3158 /***********************************************************************
3159 * macdrv_wglCopyContext
3161 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3163 CGLError err;
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)
3178 int format;
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);
3189 return NULL;
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);
3198 return NULL;
3201 return 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)
3219 int format;
3221 format = get_dc_pixel_format(hdc);
3223 if (!is_valid_pixel_format(format)) /* not set yet */
3224 format = 0;
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. */
3229 format = 1;
3232 TRACE(" hdc %p -> %d\n", hdc, format);
3233 return format;
3236 /***********************************************************************
3237 * macdrv_wglGetProcAddress
3239 static PROC macdrv_wglGetProcAddress(const char *proc)
3241 void *ret;
3243 if (!strncmp(proc, "wgl", 3)) return NULL;
3244 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3245 if (ret)
3247 if (TRACE_ON(wgl))
3249 Dl_info info;
3250 if (dladdr(ret, &info))
3251 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3252 else
3253 TRACE("%s -> %p (no library info)\n", proc, ret);
3256 else
3257 WARN("failed to find proc %s\n", debugstr_a(proc));
3258 return ret;
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");
3301 return FALSE;
3303 else if (dest->sharing)
3305 WARN("could not share display lists because dest has already shared lists before\n");
3306 return FALSE;
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;
3318 return FALSE;
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;
3330 return 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));
3343 if (!context)
3345 SetLastError(ERROR_INVALID_HANDLE);
3346 return FALSE;
3349 macdrv_flush_opengl_context(context->context);
3350 return TRUE;
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);
3377 return NULL;
3380 if (!init_opengl()) return (void *)-1;
3382 return &opengl_funcs;