2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
29 #include "wine/library.h"
30 #include "wine/debug.h"
32 #include "wine/wgl_driver.h"
33 #include "wine/wglext.h"
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
49 char wglExtensions[4096];
51 GLint max_viewport_dims[2];
54 static struct gl_info gl_info;
61 macdrv_opengl_context context;
62 CGLContextObj cglcontext;
63 macdrv_view draw_view;
64 struct wgl_pbuffer *draw_pbuffer;
65 macdrv_view read_view;
66 struct wgl_pbuffer *read_pbuffer;
67 BOOL has_been_current;
74 CGLPBufferObj pbuffer;
82 static CFMutableDictionaryRef dc_pbuffers;
84 static CRITICAL_SECTION dc_pbuffers_section;
85 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
87 0, 0, &dc_pbuffers_section,
88 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
89 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
91 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
94 static struct opengl_funcs opengl_funcs;
96 #define USE_GL_FUNC(name) #name,
97 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
101 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
103 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
104 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
105 GLenum format, GLenum type, void *pixels);
106 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
112 GLint color_bits; /* including alpha_bits */
113 int red_bits, red_shift;
114 int green_bits, green_shift;
115 int blue_bits, blue_shift;
116 GLint alpha_bits, alpha_shift;
120 static const struct color_mode color_modes[] = {
121 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE },
122 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE },
123 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE },
124 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE },
125 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE },
126 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE },
127 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE },
128 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE },
129 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE },
130 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE },
131 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE },
132 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE },
133 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE },
134 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE },
135 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE },
136 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE },
137 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE },
138 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE },
139 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE },
140 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE },
141 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE },
142 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE },
143 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE },
144 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE },
148 static const struct {
151 } depth_stencil_modes[] = {
179 GLint max_aux_buffers;
180 GLint max_sample_buffers;
187 } renderer_properties;
191 unsigned int window:1;
192 unsigned int pbuffer:1;
193 unsigned int accelerated:1;
194 unsigned int color_mode:5; /* index into color_modes table */
195 unsigned int aux_buffers:3;
196 unsigned int depth_bits:8;
197 unsigned int stencil_bits:8;
198 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
199 unsigned int double_buffer:1;
200 unsigned int stereo:1;
201 unsigned int sample_buffers:1;
202 unsigned int samples:5;
203 unsigned int backing_store:1;
211 } pixel_format_or_code;
214 static pixel_format *pixel_formats;
215 static int nb_formats, nb_displayable_formats;
218 static void *opengl_handle;
221 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
222 CGLRendererProperty property, GLint *value)
224 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
225 if (err != kCGLNoError)
226 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
227 return (err == kCGLNoError);
231 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
235 memset(properties, 0, sizeof(*properties));
237 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
238 properties->renderer_id = value & kCGLRendererIDMatchingMask;
240 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
241 properties->buffer_modes = value;
243 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
244 properties->color_modes = value;
246 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
247 properties->accum_modes = value;
249 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
250 properties->depth_modes = value;
252 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
253 properties->stencil_modes = value;
255 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
256 properties->max_aux_buffers = value;
258 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
259 properties->max_sample_buffers = value;
261 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
262 properties->max_samples = value;
264 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
265 properties->offscreen = (value != 0);
267 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
268 properties->accelerated = (value != 0);
270 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
271 properties->backing_store = (value != 0);
273 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
274 properties->window = (value != 0);
276 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
277 properties->online = (value != 0);
281 static void dump_renderer(const renderer_properties* renderer)
285 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
286 TRACE("Buffer modes:\n");
287 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
288 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
289 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
290 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
292 TRACE("Color buffer modes:\n");
293 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
295 if (renderer->color_modes & color_modes[i].mode)
297 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
298 if (color_modes[i].is_float)
304 TRACE("Accumulation buffer sizes: { ");
305 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
307 if (renderer->accum_modes & color_modes[i].mode)
308 TRACE("%d, ", color_modes[i].color_bits);
312 TRACE("Depth buffer sizes: { ");
313 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
315 if (renderer->depth_modes & depth_stencil_modes[i].mode)
316 TRACE("%d, ", depth_stencil_modes[i].bits);
320 TRACE("Stencil buffer sizes: { ");
321 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
323 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
324 TRACE("%d, ", depth_stencil_modes[i].bits);
328 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
329 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
330 TRACE("Max. Samples: %d\n", renderer->max_samples);
331 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
332 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
333 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
334 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
335 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
339 static inline UInt64 code_for_pixel_format(const pixel_format* format)
341 pixel_format_or_code pfc;
344 pfc.format = *format;
349 static inline pixel_format pixel_format_for_code(UInt64 code)
351 pixel_format_or_code pfc;
358 static const char *debugstr_pf(const pixel_format *pf)
360 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",
364 color_modes[pf->color_mode].color_bits,
365 (color_modes[pf->color_mode].is_float ? "f" : ""),
366 color_modes[pf->color_mode].alpha_bits,
369 color_modes[pf->accum_mode - 1].color_bits,
376 code_for_pixel_format(pf));
380 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
385 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
387 if ((modes & color_modes[i].mode) &&
388 color_modes[i].color_bits >= color_size &&
389 color_modes[i].alpha_bits >= alpha_size &&
390 !color_modes[i].is_float == !color_float)
392 if (best < 0) /* no existing best choice */
394 else if (color_modes[i].color_bits == color_size &&
395 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
397 /* prefer it over a best which isn't exact or which has a higher bpp */
398 if (color_modes[best].color_bits != color_size ||
399 color_modes[best].alpha_bits != alpha_size ||
400 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
403 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
404 (color_modes[i].color_bits == color_modes[best].color_bits &&
405 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
412 /* Couldn't find a match. Return first one that renderer supports. */
413 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
415 if (modes & color_modes[i].mode)
424 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
429 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
431 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
433 /* Prefer the fewest color bits, then prefer more alpha bits, then
434 prefer more bits per pixel. */
437 else if (color_modes[i].color_bits < color_modes[best].color_bits)
439 else if (color_modes[i].color_bits == color_modes[best].color_bits)
441 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
443 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
444 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
452 /* Couldn't find a match. Return last one that renderer supports. */
453 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
455 if (modes & color_modes[i].mode)
464 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
465 CFMutableSetRef pixel_format_set)
467 CGLPixelFormatAttribute attribs[64] = {
468 kCGLPFAMinimumPolicy,
469 kCGLPFAClosestPolicy,
470 kCGLPFARendererID, renderer.renderer_id,
471 kCGLPFASingleRenderer,
473 int n = 5, n_stack[16], n_stack_idx = -1;
474 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
475 new_pixel_formats = 0;
476 pixel_format request;
477 unsigned int double_buffer;
478 unsigned int accelerated = renderer.accelerated;
482 attribs[n++] = kCGLPFAAccelerated;
483 attribs[n++] = kCGLPFANoRecovery;
486 n_stack[++n_stack_idx] = n;
487 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
491 n = n_stack[n_stack_idx];
493 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
494 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
498 attribs[n++] = kCGLPFADoubleBuffer;
499 memset(&request, 0, sizeof(request));
500 request.accelerated = accelerated;
501 request.double_buffer = double_buffer;
503 /* Don't bother with in-between aux buffers values: either 0 or max. */
504 n_stack[++n_stack_idx] = n;
505 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
507 unsigned int color_mode;
509 n = n_stack[n_stack_idx];
511 attribs[n++] = kCGLPFAAuxBuffers;
513 request.aux_buffers = aux;
515 n_stack[++n_stack_idx] = n;
516 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
518 unsigned int depth_mode;
520 n = n_stack[n_stack_idx];
522 if (!(renderer.color_modes & color_modes[color_mode].mode))
525 attribs[n++] = kCGLPFAColorSize;
526 attribs[n++] = color_modes[color_mode].color_bits;
527 attribs[n++] = kCGLPFAAlphaSize;
528 attribs[n++] = color_modes[color_mode].alpha_bits;
529 if (color_modes[color_mode].is_float)
530 attribs[n++] = kCGLPFAColorFloat;
531 request.color_mode = color_mode;
533 n_stack[++n_stack_idx] = n;
534 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
536 unsigned int stencil_mode;
538 n = n_stack[n_stack_idx];
540 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
543 attribs[n++] = kCGLPFADepthSize;
544 attribs[n++] = depth_stencil_modes[depth_mode].bits;
545 request.depth_bits = depth_stencil_modes[depth_mode].bits;
547 n_stack[++n_stack_idx] = n;
548 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
552 n = n_stack[n_stack_idx];
554 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
556 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
559 attribs[n++] = kCGLPFAStencilSize;
560 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
561 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
563 /* FIXME: Could trim search space a bit here depending on GPU.
564 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
565 n_stack[++n_stack_idx] = n;
566 for (stereo = 0; stereo <= 1; stereo++)
570 n = n_stack[n_stack_idx];
572 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
573 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
577 attribs[n++] = kCGLPFAStereo;
578 request.stereo = stereo;
580 /* Starts at -1 for a 0 accum size */
581 n_stack[++n_stack_idx] = n;
582 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
584 unsigned int target_pass;
586 n = n_stack[n_stack_idx];
590 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
593 attribs[n++] = kCGLPFAAccumSize;
594 attribs[n++] = color_modes[accum_mode].color_bits;
595 request.accum_mode = accum_mode + 1;
598 request.accum_mode = 0;
600 /* Targets to request are:
601 accelerated: window OR window + pbuffer
602 software: window + pbuffer */
603 n_stack[++n_stack_idx] = n;
604 for (target_pass = 0; target_pass <= accelerated; target_pass++)
606 unsigned int samples, max_samples;
608 n = n_stack[n_stack_idx];
610 attribs[n++] = kCGLPFAWindow;
613 if (!accelerated || target_pass > 0)
615 attribs[n++] = kCGLPFAPBuffer;
621 /* FIXME: Could trim search space a bit here depending on GPU.
622 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
623 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
624 n_stack[++n_stack_idx] = n;
625 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
626 for (samples = 1; samples <= max_samples; samples *= 2)
628 unsigned int backing_store, min_backing_store, max_backing_store;
630 n = n_stack[n_stack_idx];
634 attribs[n++] = kCGLPFASampleBuffers;
635 attribs[n++] = renderer.max_sample_buffers;
636 attribs[n++] = kCGLPFASamples;
637 attribs[n++] = samples;
638 request.sample_buffers = renderer.max_sample_buffers;
639 request.samples = samples;
642 request.sample_buffers = request.samples = 0;
644 if (renderer.backing_store && double_buffer)
646 /* The software renderer seems to always preserve the backing store, whether
647 we ask for it or not. So don't bother not asking for it. */
648 min_backing_store = accelerated ? 0 : 1;
649 max_backing_store = 1;
652 min_backing_store = max_backing_store = 0;
653 n_stack[++n_stack_idx] = n;
654 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
656 CGLPixelFormatObj pix;
657 GLint virtualScreens;
660 n = n_stack[n_stack_idx];
663 attribs[n++] = kCGLPFABackingStore;
664 request.backing_store = backing_store;
668 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
669 if (err == kCGLNoError && pix)
672 GLint value, color_size, alpha_size, color_float;
674 CFNumberRef code_object;
677 memset(&pf, 0, sizeof(pf));
679 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
680 pf.accelerated = value;
681 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
682 pf.aux_buffers = value;
683 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
684 pf.depth_bits = value;
685 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
686 pf.double_buffer = value;
687 if (pf.double_buffer &&
688 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
689 pf.backing_store = value;
690 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
692 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
693 pf.sample_buffers = value;
694 if (pf.sample_buffers &&
695 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
697 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
698 pf.stencil_bits = value;
699 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
701 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
704 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
706 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
708 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
710 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
712 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
713 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
715 CGLReleasePixelFormat(pix);
717 pf_code = code_for_pixel_format(&pf);
719 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
720 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
721 dupe_pixel_formats++;
724 CFSetAddValue(pixel_format_set, code_object);
725 CFArrayAppendValue(pixel_format_array, code_object);
728 CFRelease(code_object);
730 if (pf_code == code_for_pixel_format(&request))
731 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
734 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
735 dupe ? " (duplicate)" : "");
740 failed_pixel_formats++;
741 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
744 tried_pixel_formats++;
776 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
777 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
778 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
779 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
783 /* The docs for WGL_ARB_pixel_format say:
784 Indices are assigned to pixel formats in the following order:
785 1. Accelerated pixel formats that are displayable
786 2. Accelerated pixel formats that are displayable and which have
788 3. Generic pixel formats
789 4. Accelerated pixel formats that are non displayable
791 static int pixel_format_category(pixel_format pf)
793 /* non-displayable */
797 /* non-accelerated a.k.a. software a.k.a. generic */
801 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
802 if (color_modes[pf.color_mode].is_float)
805 /* accelerated, displayable, no extended attributes */
810 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
812 CFNumberRef number1 = val1;
813 CFNumberRef number2 = val2;
815 pixel_format pf1, pf2;
816 int category1, category2;
818 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
819 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
820 pf1 = pixel_format_for_code(code1);
821 pf2 = pixel_format_for_code(code2);
822 category1 = pixel_format_category(pf1);
823 category2 = pixel_format_category(pf2);
825 if (category1 < category2)
826 return kCFCompareLessThan;
827 if (category1 > category2)
828 return kCFCompareGreaterThan;
830 /* Within a category, sort the "best" formats toward the front since that's
831 what wglChoosePixelFormatARB() has to do. The ordering implemented here
832 matches at least one Windows 7 machine's behavior.
834 /* Accelerated before unaccelerated. */
835 if (pf1.accelerated && !pf2.accelerated)
836 return kCFCompareLessThan;
837 if (!pf1.accelerated && pf2.accelerated)
838 return kCFCompareGreaterThan;
840 /* Integer color modes before floating-point. */
841 if (!color_modes[pf1.color_mode].is_float && color_modes[pf2.color_mode].is_float)
842 return kCFCompareLessThan;
843 if (color_modes[pf1.color_mode].is_float && !color_modes[pf2.color_mode].is_float)
844 return kCFCompareGreaterThan;
846 /* For integer color modes, higher color bits before lower. For floating-point mode,
848 if (color_modes[pf1.color_mode].color_bits - color_modes[pf1.color_mode].alpha_bits >
849 color_modes[pf2.color_mode].color_bits - color_modes[pf2.color_mode].alpha_bits)
850 return color_modes[pf1.color_mode].is_float ? kCFCompareGreaterThan : kCFCompareLessThan;
851 if (color_modes[pf1.color_mode].color_bits - color_modes[pf1.color_mode].alpha_bits <
852 color_modes[pf2.color_mode].color_bits - color_modes[pf2.color_mode].alpha_bits)
853 return color_modes[pf1.color_mode].is_float ? kCFCompareLessThan : kCFCompareGreaterThan;
855 /* Mac-ism: in the rare case that color bits are equal but bpp are not, prefer fewer bpp. */
856 if (color_modes[pf1.color_mode].bits_per_pixel < color_modes[pf2.color_mode].bits_per_pixel)
857 return kCFCompareLessThan;
858 if (color_modes[pf1.color_mode].bits_per_pixel > color_modes[pf2.color_mode].bits_per_pixel)
859 return kCFCompareGreaterThan;
861 /* Non-pbuffer-capable before pbuffer-capable. */
862 if (!pf1.pbuffer && pf2.pbuffer)
863 return kCFCompareLessThan;
864 if (pf1.pbuffer && !pf2.pbuffer)
865 return kCFCompareGreaterThan;
867 /* Fewer samples before more samples. */
868 if (pf1.samples < pf2.samples)
869 return kCFCompareLessThan;
870 if (pf1.samples > pf2.samples)
871 return kCFCompareGreaterThan;
873 /* Monoscopic before stereoscopic. (This is a guess.) */
874 if (!pf1.stereo && pf2.stereo)
875 return kCFCompareLessThan;
876 if (pf1.stereo && !pf2.stereo)
877 return kCFCompareGreaterThan;
879 /* Single buffered before double buffered. */
880 if (!pf1.double_buffer && pf2.double_buffer)
881 return kCFCompareLessThan;
882 if (pf1.double_buffer && !pf2.double_buffer)
883 return kCFCompareGreaterThan;
885 /* Possibly-optimized double buffering before backing-store-preserving
887 if (!pf1.backing_store && pf2.backing_store)
888 return kCFCompareLessThan;
889 if (pf1.backing_store && !pf2.backing_store)
890 return kCFCompareGreaterThan;
892 /* Bigger depth buffer before smaller depth buffer. */
893 if (pf1.depth_bits > pf2.depth_bits)
894 return kCFCompareLessThan;
895 if (pf1.depth_bits < pf2.depth_bits)
896 return kCFCompareGreaterThan;
898 /* Smaller stencil buffer before bigger stencil buffer. */
899 if (pf1.stencil_bits < pf2.stencil_bits)
900 return kCFCompareLessThan;
901 if (pf1.stencil_bits > pf2.stencil_bits)
902 return kCFCompareGreaterThan;
904 /* Smaller alpha bits before larger alpha bits. */
905 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
906 return kCFCompareLessThan;
907 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
908 return kCFCompareGreaterThan;
910 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
915 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
916 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
917 return kCFCompareLessThan;
918 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
919 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
920 return kCFCompareGreaterThan;
922 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
923 return kCFCompareLessThan;
924 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
925 return kCFCompareGreaterThan;
927 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
928 return kCFCompareLessThan;
929 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
930 return kCFCompareGreaterThan;
933 return kCFCompareGreaterThan;
935 else if (pf2.accum_mode)
936 return kCFCompareLessThan;
938 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
939 if (pf1.aux_buffers < pf2.aux_buffers)
940 return kCFCompareLessThan;
941 if (pf1.aux_buffers > pf2.aux_buffers)
942 return kCFCompareGreaterThan;
944 /* If we get here, arbitrarily sort based on code. */
946 return kCFCompareLessThan;
948 return kCFCompareGreaterThan;
949 return kCFCompareEqualTo;
953 static BOOL init_pixel_formats(void)
956 CGLRendererInfoObj renderer_info;
959 CFMutableSetRef pixel_format_set;
960 CFMutableArrayRef pixel_format_array;
966 assert(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
968 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
971 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
975 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
976 if (!pixel_format_set)
978 WARN("CFSetCreateMutable failed\n");
979 CGLDestroyRendererInfo(renderer_info);
983 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
984 if (!pixel_format_array)
986 WARN("CFArrayCreateMutable failed\n");
987 CFRelease(pixel_format_set);
988 CGLDestroyRendererInfo(renderer_info);
992 for (i = 0; i < rendererCount; i++)
994 renderer_properties renderer;
996 get_renderer_properties(renderer_info, i, &renderer);
999 TRACE("renderer_properties %d:\n", i);
1000 dump_renderer(&renderer);
1003 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1006 CFRelease(pixel_format_set);
1007 CGLDestroyRendererInfo(renderer_info);
1009 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1012 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1015 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1016 for (i = 0; i < range.length; i++)
1018 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1021 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1022 pixel_formats[i] = pixel_format_for_code(code);
1023 if (pixel_formats[i].window)
1024 nb_displayable_formats++;
1027 nb_formats = range.length;
1028 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1032 WARN("failed to allocate pixel format list\n");
1035 WARN("got no pixel formats\n");
1037 CFRelease(pixel_format_array);
1042 static inline BOOL is_valid_pixel_format(int format)
1044 return format > 0 && format <= nb_formats;
1048 static inline BOOL is_displayable_pixel_format(int format)
1050 return format > 0 && format <= nb_displayable_formats;
1054 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1056 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1057 * format in case of probing the number of pixel formats.
1059 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1061 TRACE("Returning format %d\n", format);
1062 return &pixel_formats[format - 1];
1068 static BOOL init_gl_info(void)
1070 CGDirectDisplayID display = CGMainDisplayID();
1071 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1072 CGLPixelFormatAttribute attribs[] = {
1073 kCGLPFADisplayMask, displayMask,
1076 CGLPixelFormatObj pix;
1077 GLint virtualScreens;
1079 CGLContextObj context;
1080 CGLContextObj old_context = CGLGetCurrentContext();
1083 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1084 if (err != kCGLNoError || !pix)
1086 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1090 err = CGLCreateContext(pix, NULL, &context);
1091 CGLReleasePixelFormat(pix);
1092 if (err != kCGLNoError || !context)
1094 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1098 err = CGLSetCurrentContext(context);
1099 if (err != kCGLNoError)
1101 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1102 CGLReleaseContext(context);
1106 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1107 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1108 strcpy(gl_info.glVersion, str);
1109 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1110 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1111 strcpy(gl_info.glExtensions, str);
1113 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1115 TRACE("GL version : %s\n", gl_info.glVersion);
1116 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1118 CGLSetCurrentContext(old_context);
1119 CGLReleaseContext(context);
1125 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1128 *rect = data->client_rect;
1130 if (data->cocoa_window)
1133 *window = data->cocoa_window;
1134 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1138 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1139 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1140 struct macdrv_win_data *top_data = get_win_data(top);
1142 if (top_data && top_data->cocoa_window)
1145 *window = top_data->cocoa_window;
1146 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1147 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1152 release_win_data(top_data);
1159 /***********************************************************************
1162 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1164 macdrv_window cocoa_window;
1166 TRACE("hwnd %p format %d\n", data->hwnd, format);
1168 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1170 ERR("no top-level parent with Cocoa window in this process\n");
1174 if (data->gl_view) macdrv_dispose_view(data->gl_view);
1175 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1179 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1183 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1184 wine_dbgstr_rect(&data->gl_rect));
1186 data->pixel_format = format;
1192 /**********************************************************************
1195 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1197 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1199 struct macdrv_win_data *data;
1200 const pixel_format *pf;
1201 HWND hwnd = WindowFromDC(hdc);
1204 TRACE("hdc %p format %d\n", hdc, fmt);
1206 if (!hwnd || hwnd == GetDesktopWindow())
1208 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1212 if (!(data = get_win_data(hwnd)))
1214 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1218 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1220 ret = (data->pixel_format == fmt);
1224 /* Check if fmt is in our list of supported formats to see if it is supported. */
1225 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1228 ERR("Invalid pixel format: %d\n", fmt);
1234 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1238 if (!set_win_format(data, fmt))
1240 WARN("Couldn't set format of the window, returning failure\n");
1244 TRACE("pixel format:\n");
1245 TRACE(" window: %u\n", (unsigned int)pf->window);
1246 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1247 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1248 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1249 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1250 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1251 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1252 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1253 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1254 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1255 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1256 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1257 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1258 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1262 release_win_data(data);
1263 if (ret) __wine_set_pixel_format(hwnd, fmt);
1268 /**********************************************************************
1269 * set_gl_view_parent
1271 void set_gl_view_parent(HWND hwnd, HWND parent)
1273 struct macdrv_win_data *data;
1275 if (!(data = get_win_data(hwnd))) return;
1279 macdrv_window cocoa_window;
1281 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1283 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1285 ERR("no top-level parent with Cocoa window in this process\n");
1286 macdrv_dispose_view(data->gl_view);
1287 data->gl_view = NULL;
1288 release_win_data(data);
1289 __wine_set_pixel_format( hwnd, 0 );
1293 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1296 release_win_data(data);
1300 /**********************************************************************
1301 * make_context_current
1303 static void make_context_current(struct wgl_context *context, BOOL read)
1306 struct wgl_pbuffer *pbuffer;
1310 view = context->read_view;
1311 pbuffer = context->read_pbuffer;
1315 view = context->draw_view;
1316 pbuffer = context->draw_pbuffer;
1319 if (view || !pbuffer)
1320 macdrv_make_context_current(context->context, view);
1323 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1325 CGLSetCurrentContext(context->cglcontext);
1330 /**********************************************************************
1331 * macdrv_glCopyColorTable
1333 * Hook into glCopyColorTable as part of the implementation of
1334 * wglMakeContextCurrentARB. If the context has a separate readable,
1335 * temporarily make that current, do glCopyColorTable, and then set it
1336 * back to the drawable. This is modeled after what Mesa GLX's Apple
1337 * implementation does.
1339 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1342 struct wgl_context *context = NtCurrentTeb()->glContext;
1344 if (context->read_view || context->read_pbuffer)
1345 make_context_current(context, TRUE);
1347 pglCopyColorTable(target, internalformat, x, y, width);
1349 if (context->read_view || context->read_pbuffer)
1350 make_context_current(context, FALSE);
1354 /**********************************************************************
1355 * macdrv_glCopyPixels
1357 * Hook into glCopyPixels as part of the implementation of
1358 * wglMakeContextCurrentARB. If the context has a separate readable,
1359 * temporarily make that current, do glCopyPixels, and then set it back
1360 * to the drawable. This is modeled after what Mesa GLX's Apple
1361 * implementation does.
1363 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1365 struct wgl_context *context = NtCurrentTeb()->glContext;
1367 if (context->read_view || context->read_pbuffer)
1368 make_context_current(context, TRUE);
1370 pglCopyPixels(x, y, width, height, type);
1372 if (context->read_view || context->read_pbuffer)
1373 make_context_current(context, FALSE);
1377 /**********************************************************************
1378 * macdrv_glReadPixels
1380 * Hook into glReadPixels as part of the implementation of
1381 * wglMakeContextCurrentARB. If the context has a separate readable,
1382 * temporarily make that current, do glReadPixels, and then set it back
1383 * to the drawable. This is modeled after what Mesa GLX's Apple
1384 * implementation does.
1386 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1387 GLenum format, GLenum type, void *pixels)
1389 struct wgl_context *context = NtCurrentTeb()->glContext;
1391 if (context->read_view || context->read_pbuffer)
1392 make_context_current(context, TRUE);
1394 pglReadPixels(x, y, width, height, format, type, pixels);
1396 if (context->read_view || context->read_pbuffer)
1397 make_context_current(context, FALSE);
1401 /**********************************************************************
1404 * Hook into glViewport as an opportunity to update the OpenGL context
1405 * if necessary. This is modeled after what Mesa GLX's Apple
1406 * implementation does.
1408 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1410 struct wgl_context *context = NtCurrentTeb()->glContext;
1412 macdrv_update_opengl_context(context->context);
1413 pglViewport(x, y, width, height);
1417 /***********************************************************************
1418 * macdrv_wglBindTexImageARB
1420 * WGL_ARB_render_texture: wglBindTexImageARB
1422 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1424 struct wgl_context *context = NtCurrentTeb()->glContext;
1428 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1430 if (pbuffer->no_texture)
1432 SetLastError(ERROR_INVALID_OPERATION);
1436 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1437 opengl_funcs.gl.p_glFlush();
1441 case WGL_FRONT_LEFT_ARB:
1442 if (pixel_formats[pbuffer->format].stereo)
1443 source = GL_FRONT_LEFT;
1447 case WGL_FRONT_RIGHT_ARB:
1448 source = GL_FRONT_RIGHT;
1450 case WGL_BACK_LEFT_ARB:
1451 if (pixel_formats[pbuffer->format].stereo)
1452 source = GL_BACK_LEFT;
1456 case WGL_BACK_RIGHT_ARB:
1457 source = GL_BACK_RIGHT;
1459 case WGL_AUX0_ARB: source = GL_AUX0; break;
1460 case WGL_AUX1_ARB: source = GL_AUX1; break;
1461 case WGL_AUX2_ARB: source = GL_AUX2; break;
1462 case WGL_AUX3_ARB: source = GL_AUX3; break;
1470 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1471 SetLastError(ERROR_INVALID_DATA);
1475 WARN("unknown source buffer 0x%x\n", iBuffer);
1476 SetLastError(ERROR_INVALID_DATA);
1480 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1481 if (err != kCGLNoError)
1483 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1484 SetLastError(ERROR_INVALID_OPERATION);
1492 /***********************************************************************
1493 * macdrv_wglChoosePixelFormatARB
1495 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1497 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1498 const FLOAT *pfAttribFList, UINT nMaxFormats,
1499 int *piFormats, UINT *nNumFormats)
1501 pixel_format pf, valid;
1503 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1504 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1509 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1510 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1512 FIXME("unused pfAttribFList\n");
1514 memset(&pf, 0, sizeof(pf));
1515 memset(&valid, 0, sizeof(valid));
1516 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
1517 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
1521 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1524 int value = iptr[1];
1528 case WGL_DRAW_TO_WINDOW_ARB:
1529 if (valid.window && (!pf.window != !value)) goto cant_match;
1530 pf.window = (value != 0);
1534 case WGL_DRAW_TO_BITMAP_ARB:
1537 case WGL_ACCELERATION_ARB:
1538 if (value == WGL_FULL_ACCELERATION_ARB)
1540 else if (value == WGL_NO_ACCELERATION_ARB)
1544 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1545 pf.accelerated = value;
1546 valid.accelerated = 1;
1549 case WGL_NEED_PALETTE_ARB:
1550 case WGL_NEED_SYSTEM_PALETTE_ARB:
1551 case WGL_SWAP_LAYER_BUFFERS_ARB:
1552 if (value) goto cant_match;
1555 case WGL_SWAP_METHOD_ARB:
1556 if (value == WGL_SWAP_COPY_ARB)
1558 else if (value == WGL_SWAP_UNDEFINED_ARB)
1562 if (valid.backing_store && pf.backing_store != value) goto cant_match;
1563 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
1564 pf.backing_store = value;
1565 valid.backing_store = 1;
1568 case WGL_NUMBER_OVERLAYS_ARB:
1569 case WGL_NUMBER_UNDERLAYS_ARB:
1570 if (value) goto cant_match;
1573 case WGL_SHARE_DEPTH_ARB:
1574 case WGL_SHARE_STENCIL_ARB:
1575 case WGL_SHARE_ACCUM_ARB:
1579 case WGL_SUPPORT_GDI_ARB:
1580 if (value) goto cant_match;
1583 case WGL_SUPPORT_OPENGL_ARB:
1584 if (!value) goto cant_match;
1587 case WGL_DOUBLE_BUFFER_ARB:
1588 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
1589 pf.double_buffer = (value != 0);
1590 valid.double_buffer = 1;
1591 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
1594 case WGL_STEREO_ARB:
1595 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1596 pf.stereo = (value != 0);
1600 case WGL_PIXEL_TYPE_ARB:
1601 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1603 else if (value == WGL_TYPE_RGBA_ARB)
1607 /* Mac contexts don't support rendering to unsigned floating
1608 point formats, even if GL_EXT_packed_float is supported.
1609 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1612 if (float_color != -1 && float_color != value) goto cant_match;
1613 if (srgb && value) goto cant_match;
1614 float_color = value;
1617 case WGL_COLOR_BITS_ARB:
1618 if (color_bits < value) color_bits = value;
1621 case WGL_RED_BITS_ARB:
1622 if (srgb && value > 8) goto cant_match;
1623 if (red_bits < value) red_bits = value;
1626 case WGL_GREEN_BITS_ARB:
1627 if (srgb && value > 8) goto cant_match;
1628 if (green_bits < value) green_bits = value;
1631 case WGL_BLUE_BITS_ARB:
1632 if (srgb && value > 8) goto cant_match;
1633 if (blue_bits < value) blue_bits = value;
1636 case WGL_ALPHA_BITS_ARB:
1637 if (alpha_bits < value) alpha_bits = value;
1640 case WGL_ACCUM_BITS_ARB:
1641 if (accum_bits < value) accum_bits = value;
1644 case WGL_ACCUM_RED_BITS_ARB:
1645 if (accum_red_bits < value) accum_red_bits = value;
1648 case WGL_ACCUM_GREEN_BITS_ARB:
1649 if (accum_green_bits < value) accum_green_bits = value;
1652 case WGL_ACCUM_BLUE_BITS_ARB:
1653 if (accum_blue_bits < value) accum_blue_bits = value;
1656 case WGL_ACCUM_ALPHA_BITS_ARB:
1657 if (accum_alpha_bits < value) accum_alpha_bits = value;
1660 case WGL_DEPTH_BITS_ARB:
1661 if (value > 255) goto cant_match;
1662 if (pf.depth_bits < value) pf.depth_bits = value;
1665 case WGL_STENCIL_BITS_ARB:
1666 if (value > 255) goto cant_match;
1667 if (pf.stencil_bits < value) pf.stencil_bits = value;
1670 case WGL_AUX_BUFFERS_ARB:
1671 if (value > 7) goto cant_match;
1672 if (pf.aux_buffers < value) pf.aux_buffers = value;
1675 case WGL_SAMPLE_BUFFERS_ARB:
1676 if (value > 1) goto cant_match;
1677 if (pf.sample_buffers < value) pf.sample_buffers = value;
1680 case WGL_SAMPLES_ARB:
1681 if (value > 31) goto cant_match;
1682 if (pf.samples < value) pf.samples = value;
1685 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1686 /* sRGB is only supported for 8-bit integer color components */
1687 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
1692 case WGL_NUMBER_PIXEL_FORMATS_ARB:
1693 case WGL_RED_SHIFT_ARB:
1694 case WGL_GREEN_SHIFT_ARB:
1695 case WGL_BLUE_SHIFT_ARB:
1696 case WGL_ALPHA_SHIFT_ARB:
1697 case WGL_TRANSPARENT_ARB:
1698 case WGL_TRANSPARENT_RED_VALUE_ARB:
1699 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
1700 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
1701 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
1702 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
1706 case WGL_DRAW_TO_PBUFFER_ARB:
1707 case WGL_BIND_TO_TEXTURE_RGB_ARB:
1708 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
1709 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
1710 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
1711 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
1712 pf.pbuffer = (value != 0);
1714 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1720 WARN("invalid attribute %x\n", iptr[0]);
1725 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
1727 const struct color_mode *mode;
1729 if (valid.window && pixel_formats[i].window != pf.window) continue;
1730 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
1731 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
1732 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
1733 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
1734 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
1736 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
1737 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
1738 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
1739 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
1740 if (pixel_formats[i].samples < pf.samples) continue;
1742 mode = &color_modes[pixel_formats[i].color_mode];
1743 /* If the mode doesn't have alpha, check requested color bits against
1744 bits per pixel instead of the mode's color bits. On Windows, color
1745 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1746 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1747 expects that to match such a pixel format, we need to accomodate that. */
1748 if (mode->alpha_bits)
1750 if (mode->color_bits < color_bits)
1755 if (mode->bits_per_pixel < color_bits)
1758 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
1759 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
1761 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
1762 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
1765 if (pixel_formats[i].accum_mode)
1767 mode = &color_modes[pixel_formats[i].accum_mode - 1];
1768 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
1769 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
1770 mode->alpha_bits < accum_alpha_bits)
1773 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
1776 piFormats[found++] = i;
1780 *nNumFormats = found;
1786 /**********************************************************************
1787 * macdrv_wglCreatePbufferARB
1789 * WGL_ARB_pbuffer: wglCreatePbufferARB
1791 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
1792 const int *piAttribList)
1794 struct wgl_pbuffer* pbuffer;
1796 GLenum internalFormat = 0;
1799 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
1800 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
1802 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat].pbuffer)
1804 WARN("invalid pixel format %d\n", iPixelFormat);
1805 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1809 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
1810 pbuffer->format = iPixelFormat;
1812 for ( ; piAttribList && *piAttribList; piAttribList += 2)
1814 int attr = piAttribList[0];
1815 int value = piAttribList[1];
1819 case WGL_PBUFFER_LARGEST_ARB:
1820 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
1823 case WGL_TEXTURE_FORMAT_ARB:
1826 case WGL_TEXTURE_RGBA_ARB:
1827 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
1828 internalFormat = GL_RGBA;
1830 case WGL_TEXTURE_RGB_ARB:
1831 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
1832 internalFormat = GL_RGB;
1834 case WGL_NO_TEXTURE_ARB:
1835 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
1839 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
1840 SetLastError(ERROR_INVALID_DATA);
1845 case WGL_TEXTURE_TARGET_ARB:
1849 case WGL_NO_TEXTURE_ARB:
1850 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
1853 case WGL_TEXTURE_CUBE_MAP_ARB:
1854 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
1855 target = GL_TEXTURE_CUBE_MAP;
1856 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1858 case WGL_TEXTURE_1D_ARB:
1859 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
1860 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
1862 case WGL_TEXTURE_2D_ARB:
1863 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
1864 target = GL_TEXTURE_2D;
1866 case WGL_TEXTURE_RECTANGLE_NV:
1867 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
1868 target = GL_TEXTURE_RECTANGLE;
1871 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
1872 SetLastError(ERROR_INVALID_DATA);
1877 case WGL_MIPMAP_TEXTURE_ARB:
1878 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
1879 pbuffer->max_level = 0;
1882 int size = min(iWidth, iHeight) / 2;
1885 pbuffer->max_level++;
1892 WARN("unknown attribute 0x%x\n", attr);
1893 SetLastError(ERROR_INVALID_DATA);
1898 if (!target || !internalFormat)
1900 pbuffer->no_texture = TRUE;
1901 /* no actual way to turn off ability to texture; use most permissive target */
1902 target = GL_TEXTURE_RECTANGLE;
1903 internalFormat = GL_RGB;
1906 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
1907 if (err != kCGLNoError)
1909 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
1910 pbuffer->pbuffer = NULL;
1911 if (err == kCGLBadAlloc)
1912 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
1914 SetLastError(ERROR_INVALID_DATA);
1918 if (!pbuffer->pbuffer)
1920 HeapFree(GetProcessHeap(), 0, pbuffer);
1924 TRACE(" -> %p\n", pbuffer);
1929 /**********************************************************************
1930 * macdrv_wglDestroyPbufferARB
1932 * WGL_ARB_pbuffer: wglDestroyPbufferARB
1934 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
1936 TRACE("pbuffer %p\n", pbuffer);
1937 if (pbuffer && pbuffer->pbuffer)
1938 CGLReleasePBuffer(pbuffer->pbuffer);
1939 HeapFree(GetProcessHeap(), 0, pbuffer);
1944 /**********************************************************************
1945 * macdrv_wglGetExtensionsStringARB
1947 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
1949 static const GLubyte *macdrv_wglGetExtensionsStringARB(HDC hdc)
1951 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
1952 this can be specific to the CGL renderer like we're supposed to do. */
1953 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
1954 return (const GLubyte*)gl_info.wglExtensions;
1958 /**********************************************************************
1959 * macdrv_wglGetExtensionsStringEXT
1961 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
1963 static const GLubyte *macdrv_wglGetExtensionsStringEXT(void)
1965 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
1966 return (const GLubyte*)gl_info.wglExtensions;
1970 /**********************************************************************
1971 * macdrv_wglGetPbufferDCARB
1973 * WGL_ARB_pbuffer: wglGetPbufferDCARB
1975 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
1978 struct wgl_pbuffer *prev;
1980 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1983 EnterCriticalSection(&dc_pbuffers_section);
1984 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1987 CGLReleasePBuffer(prev->pbuffer);
1988 HeapFree(GetProcessHeap(), 0, prev);
1990 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
1991 LeaveCriticalSection(&dc_pbuffers_section);
1993 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
1998 /**********************************************************************
1999 * macdrv_wglGetPixelFormatAttribivARB
2001 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2003 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2004 UINT nAttributes, const int *piAttributes, int *piValues)
2006 const pixel_format *pf;
2009 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2010 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2012 if (!nAttributes) return GL_TRUE;
2014 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2016 piValues[0] = nb_formats;
2020 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2023 WARN("invalid pixel format %d\n", iPixelFormat);
2024 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2028 for (i = 0; i < nAttributes; ++i)
2030 switch (piAttributes[i])
2032 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2033 piValues[i] = nb_formats;
2036 case WGL_DRAW_TO_WINDOW_ARB:
2037 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2040 case WGL_DRAW_TO_BITMAP_ARB:
2041 piValues[i] = GL_FALSE;
2044 case WGL_ACCELERATION_ARB:
2045 if (iLayerPlane) goto invalid_layer;
2046 if (pf->accelerated)
2047 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2049 piValues[i] = WGL_NO_ACCELERATION_ARB;
2052 case WGL_NEED_PALETTE_ARB:
2053 case WGL_NEED_SYSTEM_PALETTE_ARB:
2054 case WGL_SWAP_LAYER_BUFFERS_ARB:
2055 piValues[i] = GL_FALSE;
2058 case WGL_SWAP_METHOD_ARB:
2059 if (pf->double_buffer && pf->backing_store)
2060 piValues[i] = WGL_SWAP_COPY_ARB;
2062 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2065 case WGL_NUMBER_OVERLAYS_ARB:
2066 case WGL_NUMBER_UNDERLAYS_ARB:
2070 case WGL_TRANSPARENT_ARB:
2071 if (iLayerPlane) goto invalid_layer;
2072 piValues[i] = GL_FALSE;
2075 case WGL_TRANSPARENT_RED_VALUE_ARB:
2076 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2077 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2078 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2079 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2080 if (iLayerPlane) goto invalid_layer;
2084 case WGL_SHARE_DEPTH_ARB:
2085 case WGL_SHARE_STENCIL_ARB:
2086 case WGL_SHARE_ACCUM_ARB:
2087 if (iLayerPlane) goto invalid_layer;
2088 piValues[i] = GL_TRUE;
2091 case WGL_SUPPORT_GDI_ARB:
2092 if (iLayerPlane) goto invalid_layer;
2093 piValues[i] = GL_FALSE;
2096 case WGL_SUPPORT_OPENGL_ARB:
2097 if (iLayerPlane) goto invalid_layer;
2098 piValues[i] = GL_TRUE;
2101 case WGL_DOUBLE_BUFFER_ARB:
2102 if (iLayerPlane) goto invalid_layer;
2103 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2106 case WGL_STEREO_ARB:
2107 if (iLayerPlane) goto invalid_layer;
2108 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2111 case WGL_PIXEL_TYPE_ARB:
2112 if (iLayerPlane) goto invalid_layer;
2113 if (color_modes[pf->color_mode].is_float)
2114 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2116 piValues[i] = WGL_TYPE_RGBA_ARB;
2117 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2118 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2119 However, Mac contexts don't support rendering to unsigned floating-point
2120 formats, even when GL_EXT_packed_float is supported. */
2123 case WGL_COLOR_BITS_ARB:
2124 if (iLayerPlane) goto invalid_layer;
2125 /* If the mode doesn't have alpha, return bits per pixel instead
2126 of color bits. On Windows, color bits sometimes exceeds r+g+b
2127 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2128 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2129 pixel format, we need to accomodate that. */
2130 if (color_modes[pf->color_mode].alpha_bits)
2131 piValues[i] = color_modes[pf->color_mode].color_bits;
2133 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2136 case WGL_RED_BITS_ARB:
2137 if (iLayerPlane) goto invalid_layer;
2138 piValues[i] = color_modes[pf->color_mode].red_bits;
2141 case WGL_RED_SHIFT_ARB:
2142 if (iLayerPlane) goto invalid_layer;
2143 piValues[i] = color_modes[pf->color_mode].red_shift;
2146 case WGL_GREEN_BITS_ARB:
2147 if (iLayerPlane) goto invalid_layer;
2148 piValues[i] = color_modes[pf->color_mode].green_bits;
2151 case WGL_GREEN_SHIFT_ARB:
2152 if (iLayerPlane) goto invalid_layer;
2153 piValues[i] = color_modes[pf->color_mode].green_shift;
2156 case WGL_BLUE_BITS_ARB:
2157 if (iLayerPlane) goto invalid_layer;
2158 piValues[i] = color_modes[pf->color_mode].blue_bits;
2161 case WGL_BLUE_SHIFT_ARB:
2162 if (iLayerPlane) goto invalid_layer;
2163 piValues[i] = color_modes[pf->color_mode].blue_shift;
2166 case WGL_ALPHA_BITS_ARB:
2167 if (iLayerPlane) goto invalid_layer;
2168 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2171 case WGL_ALPHA_SHIFT_ARB:
2172 if (iLayerPlane) goto invalid_layer;
2173 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2176 case WGL_ACCUM_BITS_ARB:
2177 if (iLayerPlane) goto invalid_layer;
2179 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2184 case WGL_ACCUM_RED_BITS_ARB:
2185 if (iLayerPlane) goto invalid_layer;
2187 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2192 case WGL_ACCUM_GREEN_BITS_ARB:
2193 if (iLayerPlane) goto invalid_layer;
2195 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2200 case WGL_ACCUM_BLUE_BITS_ARB:
2201 if (iLayerPlane) goto invalid_layer;
2203 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2208 case WGL_ACCUM_ALPHA_BITS_ARB:
2209 if (iLayerPlane) goto invalid_layer;
2211 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2216 case WGL_DEPTH_BITS_ARB:
2217 if (iLayerPlane) goto invalid_layer;
2218 piValues[i] = pf->depth_bits;
2221 case WGL_STENCIL_BITS_ARB:
2222 if (iLayerPlane) goto invalid_layer;
2223 piValues[i] = pf->stencil_bits;
2226 case WGL_AUX_BUFFERS_ARB:
2227 if (iLayerPlane) goto invalid_layer;
2228 piValues[i] = pf->aux_buffers;
2231 case WGL_SAMPLE_BUFFERS_ARB:
2232 if (iLayerPlane) goto invalid_layer;
2233 piValues[i] = pf->sample_buffers;
2236 case WGL_SAMPLES_ARB:
2237 if (iLayerPlane) goto invalid_layer;
2238 piValues[i] = pf->samples;
2241 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2242 if (iLayerPlane) goto invalid_layer;
2243 /* sRGB is only supported for 8-bit integer color components */
2244 if (color_modes[pf->color_mode].red_bits == 8 &&
2245 color_modes[pf->color_mode].green_bits == 8 &&
2246 color_modes[pf->color_mode].blue_bits == 8 &&
2247 !color_modes[pf->color_mode].is_float)
2248 piValues[i] = GL_TRUE;
2250 piValues[i] = GL_FALSE;
2253 case WGL_DRAW_TO_PBUFFER_ARB:
2254 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2255 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2256 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2259 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2260 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2261 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2264 case WGL_MAX_PBUFFER_WIDTH_ARB:
2265 piValues[i] = gl_info.max_viewport_dims[0];
2268 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2269 piValues[i] = gl_info.max_viewport_dims[1];
2272 case WGL_MAX_PBUFFER_PIXELS_ARB:
2273 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2277 WARN("invalid attribute %x\n", piAttributes[i]);
2281 TRACE("piAttributes[%d] (%x) -> %x\n", i, piAttributes[i], piValues[i]);
2287 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2292 /**********************************************************************
2293 * macdrv_wglGetPixelFormatAttribfvARB
2295 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2297 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2298 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2303 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2304 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2306 /* Allocate a temporary array to store integer values */
2307 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2310 ERR("couldn't allocate %d array\n", nAttributes);
2314 /* Piggy-back on wglGetPixelFormatAttribivARB */
2315 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2320 /* Convert integer values to float. Should also check for attributes
2321 that can give decimal values here */
2322 for (i = 0; i < nAttributes; i++)
2323 pfValues[i] = attr[i];
2326 HeapFree(GetProcessHeap(), 0, attr);
2331 /**********************************************************************
2332 * macdrv_wglGetSwapIntervalEXT
2334 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2336 static int macdrv_wglGetSwapIntervalEXT(void)
2338 struct wgl_context *context = NtCurrentTeb()->glContext;
2344 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2345 if (err != kCGLNoError)
2347 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2348 err, CGLErrorString(err));
2356 /***********************************************************************
2357 * macdrv_wglMakeContextCurrentARB
2359 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2361 * This is not supported directly by OpenGL on the Mac. We emulate it
2362 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2363 * temporarily swap the drawable. This follows the technique used in
2364 * the implementation of Mesa GLX for Apple.
2366 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
2368 struct macdrv_win_data *data;
2371 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
2372 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
2376 macdrv_make_context_current(NULL, NULL);
2377 NtCurrentTeb()->glContext = NULL;
2381 if ((hwnd = WindowFromDC(draw_hdc)))
2383 if (!(data = get_win_data(hwnd)))
2385 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
2389 if (!data->pixel_format)
2391 WARN("no pixel format set\n");
2392 release_win_data(data);
2393 SetLastError(ERROR_INVALID_HANDLE);
2396 if (context->format != data->pixel_format)
2398 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
2399 release_win_data(data);
2400 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2404 context->draw_view = data->gl_view;
2405 context->draw_pbuffer = NULL;
2406 release_win_data(data);
2410 struct wgl_pbuffer *pbuffer;
2412 EnterCriticalSection(&dc_pbuffers_section);
2413 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2416 if (context->format != pbuffer->format)
2418 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
2419 LeaveCriticalSection(&dc_pbuffers_section);
2420 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2426 WARN("no window or pbuffer for DC\n");
2427 LeaveCriticalSection(&dc_pbuffers_section);
2428 SetLastError(ERROR_INVALID_HANDLE);
2432 context->draw_view = NULL;
2433 context->draw_pbuffer = pbuffer;
2434 LeaveCriticalSection(&dc_pbuffers_section);
2437 context->read_view = NULL;
2438 context->read_pbuffer = NULL;
2439 if (read_hdc && read_hdc != draw_hdc)
2441 if ((hwnd = WindowFromDC(read_hdc)))
2443 if ((data = get_win_data(hwnd)))
2445 if (data->gl_view != context->draw_view)
2446 context->read_view = data->gl_view;
2447 release_win_data(data);
2452 EnterCriticalSection(&dc_pbuffers_section);
2453 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
2454 LeaveCriticalSection(&dc_pbuffers_section);
2458 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2459 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
2461 make_context_current(context, FALSE);
2462 context->has_been_current = TRUE;
2463 NtCurrentTeb()->glContext = context;
2469 /**********************************************************************
2470 * macdrv_wglQueryPbufferARB
2472 * WGL_ARB_pbuffer: wglQueryPbufferARB
2474 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2480 GLenum internalFormat;
2483 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
2485 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
2486 if (err != kCGLNoError)
2488 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
2489 SetLastError(ERROR_INVALID_HANDLE);
2495 case WGL_PBUFFER_WIDTH_ARB:
2498 case WGL_PBUFFER_HEIGHT_ARB:
2501 case WGL_PBUFFER_LOST_ARB:
2502 /* Mac PBuffers can't be lost */
2503 *piValue = GL_FALSE;
2505 case WGL_TEXTURE_FORMAT_ARB:
2506 if (pbuffer->no_texture)
2507 *piValue = WGL_NO_TEXTURE_ARB;
2508 else switch (internalFormat)
2511 *piValue = WGL_TEXTURE_RGBA_ARB;
2515 *piValue = WGL_TEXTURE_RGB_ARB;
2519 case WGL_TEXTURE_TARGET_ARB:
2520 if (pbuffer->no_texture)
2521 *piValue = WGL_NO_TEXTURE_ARB;
2522 else switch (target)
2524 case GL_TEXTURE_CUBE_MAP:
2525 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
2528 *piValue = WGL_TEXTURE_2D_ARB;
2530 case GL_TEXTURE_RECTANGLE:
2532 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2536 case WGL_MIPMAP_TEXTURE_ARB:
2537 *piValue = (pbuffer->max_level > 0);
2539 case WGL_MIPMAP_LEVEL_ARB:
2540 *piValue = pbuffer->level;
2542 case WGL_CUBE_MAP_FACE_ARB:
2543 switch (pbuffer->face)
2545 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2547 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2549 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2550 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2552 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2553 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2555 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2556 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2558 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2559 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2561 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2562 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2567 WARN("invalid attribute 0x%x\n", iAttribute);
2568 SetLastError(ERROR_INVALID_DATA);
2576 /**********************************************************************
2577 * macdrv_wglReleasePbufferDCARB
2579 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2581 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
2583 struct wgl_pbuffer *prev;
2585 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
2587 EnterCriticalSection(&dc_pbuffers_section);
2589 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2592 if (prev != pbuffer)
2593 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
2594 CGLReleasePBuffer(prev->pbuffer);
2595 HeapFree(GetProcessHeap(), 0, prev);
2596 CFDictionaryRemoveValue(dc_pbuffers, hdc);
2600 LeaveCriticalSection(&dc_pbuffers_section);
2602 return hdc && DeleteDC(hdc);
2606 /**********************************************************************
2607 * macdrv_wglReleaseTexImageARB
2609 * WGL_ARB_render_texture: wglReleaseTexImageARB
2611 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2613 struct wgl_context *context = NtCurrentTeb()->glContext;
2616 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2618 if (pbuffer->no_texture)
2620 SetLastError(ERROR_INVALID_OPERATION);
2624 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
2625 if (err != kCGLNoError)
2627 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2628 SetLastError(ERROR_INVALID_OPERATION);
2636 /**********************************************************************
2637 * macdrv_wglSetPbufferAttribARB
2639 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2641 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
2643 struct wgl_context *context = NtCurrentTeb()->glContext;
2645 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
2647 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2649 int attr = piAttribList[0];
2650 int value = piAttribList[1];
2653 case WGL_MIPMAP_LEVEL_ARB:
2654 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2655 pbuffer->level = value;
2657 case WGL_CUBE_MAP_FACE_ARB:
2660 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2661 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2662 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2664 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2665 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2666 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
2668 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2669 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2670 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2672 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2673 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2674 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
2676 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2677 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2678 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2680 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2681 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2682 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2685 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
2686 SetLastError(ERROR_INVALID_DATA);
2691 WARN("invalide attribute 0x%x\n", attr);
2692 SetLastError(ERROR_INVALID_DATA);
2697 if (context && context->draw_pbuffer == pbuffer)
2698 make_context_current(context, FALSE);
2704 /**********************************************************************
2705 * macdrv_wglSetPixelFormatWINE
2707 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2709 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
2711 return set_pixel_format(hdc, fmt, TRUE);
2715 /**********************************************************************
2716 * macdrv_wglSwapIntervalEXT
2718 * WGL_EXT_swap_control: wglSwapIntervalEXT
2720 static BOOL macdrv_wglSwapIntervalEXT(int interval)
2722 struct wgl_context *context = NtCurrentTeb()->glContext;
2726 TRACE("interval %d\n", interval);
2730 SetLastError(ERROR_INVALID_DATA);
2738 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2739 if (err != kCGLNoError)
2741 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2742 err, CGLErrorString(err));
2743 SetLastError(ERROR_GEN_FAILURE);
2751 static void register_extension(const char *ext)
2753 if (gl_info.wglExtensions[0])
2754 strcat(gl_info.wglExtensions, " ");
2755 strcat(gl_info.wglExtensions, ext);
2757 TRACE("'%s'\n", ext);
2760 static void load_extensions(void)
2765 register_extension("WGL_ARB_extensions_string");
2766 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
2768 register_extension("WGL_ARB_make_current_read");
2769 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
2770 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
2772 register_extension("WGL_ARB_pixel_format");
2773 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
2774 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
2775 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
2777 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
2779 register_extension("WGL_ARB_pixel_format_float");
2780 register_extension("WGL_ATI_pixel_format_float");
2783 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
2784 register_extension("WGL_ARB_multisample");
2786 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
2787 register_extension("WGL_ARB_framebuffer_sRGB");
2789 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
2791 register_extension("WGL_ARB_pbuffer");
2792 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
2793 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
2794 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
2795 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
2796 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
2798 register_extension("WGL_ARB_render_texture");
2799 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
2800 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
2801 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
2803 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
2804 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
2805 register_extension("WGL_NV_render_texture_rectangle");
2809 WGL_ARB_create_context: wglCreateContextAttribsARB
2810 WGL_ARB_create_context_profile
2816 register_extension("WGL_EXT_extensions_string");
2817 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
2819 register_extension("WGL_EXT_swap_control");
2820 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
2821 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
2823 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
2824 check for either, so register them separately. */
2825 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
2826 register_extension("WGL_EXT_framebuffer_sRGB");
2828 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
2829 register_extension("WGL_EXT_pixel_format_packed_float");
2832 * WINE-specific WGL Extensions
2835 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
2836 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
2838 register_extension("WGL_WINE_pixel_format_passthrough");
2839 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
2843 static BOOL init_opengl(void)
2845 static int init_done;
2849 if (init_done) return (opengl_handle != NULL);
2854 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
2857 WARN("CFDictionaryCreateMutable failed\n");
2861 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
2864 ERR("Failed to load OpenGL: %s\n", buffer);
2865 ERR("OpenGL support is disabled.\n");
2869 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
2871 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
2873 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
2878 /* redirect some standard OpenGL functions */
2879 #define REDIRECT(func) \
2880 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
2881 REDIRECT(glCopyPixels);
2882 REDIRECT(glReadPixels);
2883 REDIRECT(glViewport);
2886 /* redirect some OpenGL extension functions */
2887 #define REDIRECT(func) \
2888 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
2889 REDIRECT(glCopyColorTable);
2892 if (!init_gl_info())
2896 if (!init_pixel_formats())
2902 wine_dlclose(opengl_handle, NULL, 0);
2903 opengl_handle = NULL;
2908 /***********************************************************************
2911 * Synchronize the Mac GL view position with the Windows child window
2914 void sync_gl_view(struct macdrv_win_data *data)
2918 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
2920 if (!data->gl_view) return;
2922 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
2924 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
2925 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
2926 data->gl_rect = rect;
2931 static int get_dc_pixel_format(HDC hdc)
2936 if ((hwnd = WindowFromDC(hdc)))
2938 struct macdrv_win_data *data;
2940 if (!(data = get_win_data(hwnd)))
2942 FIXME("DC for window %p of other process: not implemented\n", hwnd);
2946 format = data->pixel_format;
2947 release_win_data(data);
2951 struct wgl_pbuffer *pbuffer;
2953 EnterCriticalSection(&dc_pbuffers_section);
2954 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2956 format = pbuffer->format;
2959 WARN("no window or pbuffer for DC %p\n", hdc);
2962 LeaveCriticalSection(&dc_pbuffers_section);
2969 /**********************************************************************
2972 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
2974 const pixel_format *pf;
2975 CGLPixelFormatAttribute attribs[64];
2977 CGLPixelFormatObj pix;
2978 GLint virtualScreens;
2982 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
2985 ERR("Invalid pixel format %d, expect problems!\n", context->format);
2986 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2990 attribs[n++] = kCGLPFAMinimumPolicy;
2991 attribs[n++] = kCGLPFAClosestPolicy;
2993 if (pf->accelerated)
2994 attribs[n++] = kCGLPFAAccelerated;
2997 attribs[n++] = kCGLPFARendererID;
2998 attribs[n++] = kCGLRendererGenericFloatID;
3001 if (pf->double_buffer)
3002 attribs[n++] = kCGLPFADoubleBuffer;
3004 attribs[n++] = kCGLPFAAuxBuffers;
3005 attribs[n++] = pf->aux_buffers;
3007 attribs[n++] = kCGLPFAColorSize;
3008 attribs[n++] = color_modes[pf->color_mode].color_bits;
3009 attribs[n++] = kCGLPFAAlphaSize;
3010 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
3011 if (color_modes[pf->color_mode].is_float)
3012 attribs[n++] = kCGLPFAColorFloat;
3014 attribs[n++] = kCGLPFADepthSize;
3015 attribs[n++] = pf->depth_bits;
3017 attribs[n++] = kCGLPFAStencilSize;
3018 attribs[n++] = pf->stencil_bits;
3021 attribs[n++] = kCGLPFAStereo;
3025 attribs[n++] = kCGLPFAAccumSize;
3026 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3030 attribs[n++] = kCGLPFAWindow;
3032 attribs[n++] = kCGLPFAPBuffer;
3034 if (pf->sample_buffers && pf->samples)
3036 attribs[n++] = kCGLPFASampleBuffers;
3037 attribs[n++] = pf->sample_buffers;
3038 attribs[n++] = kCGLPFASamples;
3039 attribs[n++] = pf->samples;
3042 if (pf->backing_store)
3043 attribs[n++] = kCGLPFABackingStore;
3047 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3048 if (err != kCGLNoError || !pix)
3050 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3054 err = CGLCreateContext(pix, share, &context->cglcontext);
3055 CGLReleasePixelFormat(pix);
3056 if (err != kCGLNoError || !context->cglcontext)
3058 context->cglcontext = NULL;
3059 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
3063 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3064 a context is 1. CGL contexts default to 0, so we need to set it. */
3066 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&swap_interval);
3067 if (err != kCGLNoError)
3068 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err, CGLErrorString(err));
3070 context->context = macdrv_create_opengl_context(context->cglcontext);
3071 CGLReleaseContext(context->cglcontext);
3072 if (!context->context)
3074 WARN("macdrv_create_opengl_context() failed\n");
3078 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3084 /**********************************************************************
3085 * macdrv_wglDescribePixelFormat
3087 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3089 int ret = nb_formats;
3090 const pixel_format *pf;
3091 const struct color_mode *mode;
3093 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3095 if (fmt <= 0 || fmt > ret) return ret;
3096 if (size < sizeof(*descr)) return 0;
3098 pf = &pixel_formats[fmt - 1];
3100 memset(descr, 0, sizeof(*descr));
3101 descr->nSize = sizeof(*descr);
3102 descr->nVersion = 1;
3104 descr->dwFlags = PFD_SUPPORT_OPENGL;
3105 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3106 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3107 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3108 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3109 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3111 descr->iPixelType = PFD_TYPE_RGBA;
3113 mode = &color_modes[pf->color_mode];
3114 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3115 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3116 R8G8B8A0 pixel format). If an app depends on that and expects that
3117 cColorBits >= 32 for such a pixel format, we need to accomodate that. */
3118 if (mode->alpha_bits)
3119 descr->cColorBits = mode->color_bits;
3121 descr->cColorBits = mode->bits_per_pixel;
3122 descr->cRedBits = mode->red_bits;
3123 descr->cRedShift = mode->red_shift;
3124 descr->cGreenBits = mode->green_bits;
3125 descr->cGreenShift = mode->green_shift;
3126 descr->cBlueBits = mode->blue_bits;
3127 descr->cBlueShift = mode->blue_shift;
3128 descr->cAlphaBits = mode->alpha_bits;
3129 descr->cAlphaShift = mode->alpha_shift;
3133 mode = &color_modes[pf->accum_mode - 1];
3134 descr->cAccumBits = mode->color_bits;
3135 descr->cAccumRedBits = mode->red_bits;
3136 descr->cAccumGreenBits = mode->green_bits;
3137 descr->cAccumBlueBits = mode->blue_bits;
3138 descr->cAccumAlphaBits = mode->alpha_bits;
3141 descr->cDepthBits = pf->depth_bits;
3142 descr->cStencilBits = pf->stencil_bits;
3143 descr->cAuxBuffers = pf->aux_buffers;
3144 descr->iLayerType = PFD_MAIN_PLANE;
3148 /***********************************************************************
3149 * macdrv_wglCopyContext
3151 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3155 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3157 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3158 if (err != kCGLNoError)
3159 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3160 return (err == kCGLNoError);
3163 /***********************************************************************
3164 * macdrv_wglCreateContext
3166 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3169 struct wgl_context *context;
3171 TRACE("hdc %p\n", hdc);
3173 format = get_dc_pixel_format(hdc);
3175 if (!is_valid_pixel_format(format))
3177 ERR("Invalid pixel format %d, expect problems!\n", format);
3178 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3182 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3184 context->format = format;
3185 if (!create_context(context, NULL))
3187 HeapFree(GetProcessHeap(), 0, context);
3194 /***********************************************************************
3195 * macdrv_wglDeleteContext
3197 static void macdrv_wglDeleteContext(struct wgl_context *context)
3199 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3200 macdrv_dispose_opengl_context(context->context);
3201 HeapFree(GetProcessHeap(), 0, context);
3204 /***********************************************************************
3205 * macdrv_wglGetPixelFormat
3207 static int macdrv_wglGetPixelFormat(HDC hdc)
3211 format = get_dc_pixel_format(hdc);
3213 if (!is_valid_pixel_format(format)) /* not set yet */
3215 else if (!is_displayable_pixel_format(format))
3217 /* Non-displayable formats can't be used with traditional WGL calls.
3218 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3222 TRACE(" hdc %p -> %d\n", hdc, format);
3226 /***********************************************************************
3227 * macdrv_wglGetProcAddress
3229 static PROC macdrv_wglGetProcAddress(const char *proc)
3233 if (!strncmp(proc, "wgl", 3)) return NULL;
3234 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3240 if (dladdr(ret, &info))
3241 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3243 TRACE("%s -> %p (no library info)\n", proc, ret);
3247 WARN("failed to find proc %s\n", debugstr_a(proc));
3251 /***********************************************************************
3252 * macdrv_wglMakeCurrent
3254 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3256 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3257 (context ? context->cglcontext : NULL));
3259 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3262 /**********************************************************************
3263 * macdrv_wglSetPixelFormat
3265 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3267 return set_pixel_format(hdc, fmt, FALSE);
3270 /***********************************************************************
3271 * macdrv_wglShareLists
3273 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3275 macdrv_opengl_context saved_context;
3276 CGLContextObj saved_cglcontext;
3278 TRACE("org %p dest %p\n", org, dest);
3280 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3281 * at context creation time but in case of WGL it is done using wglShareLists.
3283 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3284 * and when a program requests sharing we recreate the destination context if it hasn't been made
3285 * current or when it hasn't shared display lists before.
3288 if (dest->has_been_current)
3290 WARN("could not share display lists, the destination context has been current already\n");
3293 else if (dest->sharing)
3295 WARN("could not share display lists because dest has already shared lists before\n");
3299 /* Re-create the Mac context and share display lists */
3300 saved_context = dest->context;
3301 saved_cglcontext = dest->cglcontext;
3302 dest->context = NULL;
3303 dest->cglcontext = NULL;
3304 if (!create_context(dest, org->cglcontext))
3306 dest->context = saved_context;
3307 dest->cglcontext = saved_cglcontext;
3311 /* Implicitly disposes of saved_cglcontext. */
3312 macdrv_dispose_opengl_context(saved_context);
3314 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3315 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3317 org->sharing = TRUE;
3318 dest->sharing = TRUE;
3323 /**********************************************************************
3324 * macdrv_wglSwapBuffers
3326 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3328 struct wgl_context *context = NtCurrentTeb()->glContext;
3330 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3331 (context ? context->cglcontext : NULL));
3335 SetLastError(ERROR_INVALID_HANDLE);
3339 macdrv_flush_opengl_context(context->context);
3343 static struct opengl_funcs opengl_funcs =
3346 macdrv_wglCopyContext, /* p_wglCopyContext */
3347 macdrv_wglCreateContext, /* p_wglCreateContext */
3348 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3349 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3350 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3351 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3352 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3353 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3354 macdrv_wglShareLists, /* p_wglShareLists */
3355 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3359 /**********************************************************************
3360 * macdrv_wine_get_wgl_driver
3362 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3364 if (version != WINE_WGL_DRIVER_VERSION)
3366 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3370 if (!init_opengl()) return (void *)-1;
3372 return &opengl_funcs;