winemac: Add a new registry setting, OpenGLSurfaceMode, to control how GL surfaces...
[wine.git] / dlls / winemac.drv / opengl.c
bloba6f1440a00458bfaa8689a88f44b4538f2d9a4bf
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 "winnt.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32 #include "wine/wgl.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
36 #define __gl_h_
37 #define __gltypes_h_
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
41 #include <dlfcn.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 struct gl_info {
47 char *glVersion;
48 char *glExtensions;
50 char wglExtensions[4096];
52 GLint max_viewport_dims[2];
54 unsigned int max_major, max_minor;
57 static struct gl_info gl_info;
60 struct wgl_context
62 struct list entry;
63 int format;
64 macdrv_opengl_context context;
65 CGLContextObj cglcontext;
66 HWND draw_hwnd;
67 macdrv_view draw_view;
68 struct wgl_pbuffer *draw_pbuffer;
69 macdrv_view read_view;
70 struct wgl_pbuffer *read_pbuffer;
71 BOOL has_been_current;
72 BOOL sharing;
73 LONG update_swap_interval;
74 DWORD last_flush_time;
75 UINT major;
78 static struct list context_list = LIST_INIT(context_list);
80 static CRITICAL_SECTION context_section;
81 static CRITICAL_SECTION_DEBUG critsect_debug =
83 0, 0, &context_section,
84 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
85 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
87 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
90 struct wgl_pbuffer
92 CGLPBufferObj pbuffer;
93 int format;
94 BOOL no_texture;
95 int max_level;
96 GLint level;
97 GLenum face;
100 static CFMutableDictionaryRef dc_pbuffers;
102 static CRITICAL_SECTION dc_pbuffers_section;
103 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
105 0, 0, &dc_pbuffers_section,
106 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
107 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
109 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
112 static struct opengl_funcs opengl_funcs;
114 #define USE_GL_FUNC(name) #name,
115 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
116 #undef USE_GL_FUNC
119 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
120 GLsizei width);
121 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
122 static void (*pglFinish)(void);
123 static void (*pglFlush)(void);
124 static void (*pglFlushRenderAPPLE)(void);
125 static const GLubyte *(*pglGetString)(GLenum name);
126 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
127 GLenum format, GLenum type, void *pixels);
128 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
131 struct color_mode {
132 GLint mode;
133 int bits_per_pixel;
134 GLint color_bits; /* including alpha_bits */
135 int red_bits, red_shift;
136 int green_bits, green_shift;
137 int blue_bits, blue_shift;
138 GLint alpha_bits, alpha_shift;
139 BOOL is_float;
140 int color_ordering;
143 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
144 observations of the behavior of Windows systems, but also subjective judgments
145 about what color formats are more "normal" than others.
147 On at least some Windows systems, integer color formats are listed before
148 floating-point formats. Within the integer formats, higher color bits were
149 usually listed before lower color bits, while for floating-point formats it
150 was the reverse. However, that leads D3D to select 64-bit integer formats in
151 preference to 32-bit formats when the latter would be sufficient. It seems
152 that a 32-bit format is much more likely to be normally used in that case.
154 Also, there are certain odd color formats supported on the Mac which seem like
155 they would be less appropriate than more common ones. For instance, the color
156 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
157 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
158 components.
160 For two color formats which differ only in whether or not they have alpha bits,
161 we use the same ordering. pixel_format_comparator() gives alpha bits a
162 different weight than color formats.
164 static const struct color_mode color_modes[] = {
165 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
166 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
167 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
168 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
169 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
170 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
171 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
172 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
173 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
174 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
175 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
176 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
177 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
178 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
179 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
180 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
181 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
182 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
183 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
184 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
185 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
186 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
187 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
188 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
192 static const struct {
193 GLint mode;
194 int bits;
195 } depth_stencil_modes[] = {
196 { kCGL0Bit, 0 },
197 { kCGL1Bit, 1 },
198 { kCGL2Bit, 2 },
199 { kCGL3Bit, 3 },
200 { kCGL4Bit, 4 },
201 { kCGL5Bit, 5 },
202 { kCGL6Bit, 6 },
203 { kCGL8Bit, 8 },
204 { kCGL10Bit, 10 },
205 { kCGL12Bit, 12 },
206 { kCGL16Bit, 16 },
207 { kCGL24Bit, 24 },
208 { kCGL32Bit, 32 },
209 { kCGL48Bit, 48 },
210 { kCGL64Bit, 64 },
211 { kCGL96Bit, 96 },
212 { kCGL128Bit, 128 },
216 typedef struct {
217 GLint renderer_id;
218 GLint buffer_modes;
219 GLint color_modes;
220 GLint accum_modes;
221 GLint depth_modes;
222 GLint stencil_modes;
223 GLint max_aux_buffers;
224 GLint max_sample_buffers;
225 GLint max_samples;
226 BOOL offscreen;
227 BOOL accelerated;
228 BOOL backing_store;
229 BOOL window;
230 BOOL online;
231 } renderer_properties;
234 typedef struct {
235 unsigned int window:1;
236 unsigned int pbuffer:1;
237 unsigned int accelerated:1;
238 unsigned int color_mode:5; /* index into color_modes table */
239 unsigned int aux_buffers:3;
240 unsigned int depth_bits:8;
241 unsigned int stencil_bits:8;
242 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
243 unsigned int double_buffer:1;
244 unsigned int stereo:1;
245 unsigned int sample_buffers:1;
246 unsigned int samples:5;
247 unsigned int backing_store:1;
248 } pixel_format;
251 typedef union
253 pixel_format format;
254 UInt64 code;
255 } pixel_format_or_code;
256 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
259 static pixel_format *pixel_formats;
260 static int nb_formats, nb_displayable_formats;
263 static void *opengl_handle;
266 static const char* debugstr_attrib(int attrib, int value)
268 static const struct {
269 int attrib;
270 const char *name;
271 } attrib_names[] = {
272 #define ATTRIB(a) { a, #a }
273 ATTRIB(WGL_ACCELERATION_ARB),
274 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
275 ATTRIB(WGL_ACCUM_BITS_ARB),
276 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
277 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
278 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
279 ATTRIB(WGL_ALPHA_BITS_ARB),
280 ATTRIB(WGL_ALPHA_SHIFT_ARB),
281 ATTRIB(WGL_AUX_BUFFERS_ARB),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
283 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
286 ATTRIB(WGL_BLUE_BITS_ARB),
287 ATTRIB(WGL_BLUE_SHIFT_ARB),
288 ATTRIB(WGL_COLOR_BITS_ARB),
289 ATTRIB(WGL_DEPTH_BITS_ARB),
290 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
291 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
292 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
293 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
294 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
295 ATTRIB(WGL_GREEN_BITS_ARB),
296 ATTRIB(WGL_GREEN_SHIFT_ARB),
297 ATTRIB(WGL_NEED_PALETTE_ARB),
298 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
299 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
300 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
301 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
302 ATTRIB(WGL_PIXEL_TYPE_ARB),
303 ATTRIB(WGL_RED_BITS_ARB),
304 ATTRIB(WGL_RED_SHIFT_ARB),
305 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
306 ATTRIB(WGL_SAMPLES_ARB),
307 ATTRIB(WGL_SHARE_ACCUM_ARB),
308 ATTRIB(WGL_SHARE_DEPTH_ARB),
309 ATTRIB(WGL_SHARE_STENCIL_ARB),
310 ATTRIB(WGL_STENCIL_BITS_ARB),
311 ATTRIB(WGL_STEREO_ARB),
312 ATTRIB(WGL_SUPPORT_GDI_ARB),
313 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
314 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
315 ATTRIB(WGL_SWAP_METHOD_ARB),
316 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
317 ATTRIB(WGL_TRANSPARENT_ARB),
318 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
319 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
320 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
321 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
322 #undef ATTRIB
324 int i;
325 const char *attrib_name = NULL;
326 const char *value_name = NULL;
328 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
330 if (attrib_names[i].attrib == attrib)
332 attrib_name = attrib_names[i].name;
333 break;
337 if (!attrib_name)
338 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
340 switch (attrib)
342 case WGL_ACCELERATION_ARB:
343 switch (value)
345 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
346 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
347 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
349 break;
350 case WGL_PIXEL_TYPE_ARB:
351 switch (value)
353 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
354 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
355 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
356 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
358 break;
359 case WGL_SWAP_METHOD_ARB:
360 switch (value)
362 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
363 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
364 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
366 break;
369 if (!value_name)
370 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
372 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
376 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
377 CGLRendererProperty property, GLint *value)
379 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
380 if (err != kCGLNoError)
381 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
382 return (err == kCGLNoError);
386 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
388 GLint value;
390 memset(properties, 0, sizeof(*properties));
392 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
393 properties->renderer_id = value & kCGLRendererIDMatchingMask;
395 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
396 properties->buffer_modes = value;
398 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
399 properties->color_modes = value;
401 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
402 properties->accum_modes = value;
404 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
405 properties->depth_modes = value;
407 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
408 properties->stencil_modes = value;
410 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
411 properties->max_aux_buffers = value;
413 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
414 properties->max_sample_buffers = value;
416 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
417 properties->max_samples = value;
419 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
420 properties->offscreen = (value != 0);
422 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
423 properties->accelerated = (value != 0);
425 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
426 properties->backing_store = (value != 0);
428 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
429 properties->window = (value != 0);
431 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
432 properties->online = (value != 0);
436 static void dump_renderer(const renderer_properties* renderer)
438 int i;
440 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
441 TRACE("Buffer modes:\n");
442 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
443 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
444 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
445 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
447 TRACE("Color buffer modes:\n");
448 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
450 if (renderer->color_modes & color_modes[i].mode)
452 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
453 if (color_modes[i].is_float)
454 TRACE(", Float");
455 TRACE("\n");
459 TRACE("Accumulation buffer sizes: { ");
460 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
462 if (renderer->accum_modes & color_modes[i].mode)
463 TRACE("%d, ", color_modes[i].color_bits);
465 TRACE("}\n");
467 TRACE("Depth buffer sizes: { ");
468 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
470 if (renderer->depth_modes & depth_stencil_modes[i].mode)
471 TRACE("%d, ", depth_stencil_modes[i].bits);
473 TRACE("}\n");
475 TRACE("Stencil buffer sizes: { ");
476 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
478 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
479 TRACE("%d, ", depth_stencil_modes[i].bits);
481 TRACE("}\n");
483 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
484 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
485 TRACE("Max. Samples: %d\n", renderer->max_samples);
486 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
487 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
488 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
489 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
490 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
494 static inline UInt64 code_for_pixel_format(const pixel_format* format)
496 pixel_format_or_code pfc;
498 pfc.code = 0;
499 pfc.format = *format;
500 return pfc.code;
504 static inline pixel_format pixel_format_for_code(UInt64 code)
506 pixel_format_or_code pfc;
508 pfc.code = code;
509 return pfc.format;
513 static const char *debugstr_pf(const pixel_format *pf)
515 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",
516 pf->window,
517 pf->pbuffer,
518 pf->accelerated,
519 color_modes[pf->color_mode].color_bits,
520 (color_modes[pf->color_mode].is_float ? "f" : ""),
521 color_modes[pf->color_mode].alpha_bits,
522 pf->depth_bits,
523 pf->stencil_bits,
524 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
525 pf->aux_buffers,
526 pf->backing_store,
527 pf->double_buffer,
528 pf->stereo,
529 pf->sample_buffers,
530 pf->samples,
531 code_for_pixel_format(pf));
535 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
537 int best = -1;
538 int i;
540 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
542 if ((modes & color_modes[i].mode) &&
543 color_modes[i].color_bits >= color_size &&
544 color_modes[i].alpha_bits >= alpha_size &&
545 !color_modes[i].is_float == !color_float)
547 if (best < 0) /* no existing best choice */
548 best = i;
549 else if (color_modes[i].color_bits == color_size &&
550 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
552 /* prefer it over a best which isn't exact or which has a higher bpp */
553 if (color_modes[best].color_bits != color_size ||
554 color_modes[best].alpha_bits != alpha_size ||
555 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
556 best = i;
558 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
559 (color_modes[i].color_bits == color_modes[best].color_bits &&
560 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
561 best = i;
565 if (best < 0)
567 /* Couldn't find a match. Return first one that renderer supports. */
568 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
570 if (modes & color_modes[i].mode)
571 return i;
575 return best;
579 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
581 int best = -1;
582 int i;
584 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
586 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
588 /* Prefer the fewest color bits, then prefer more alpha bits, then
589 prefer more bits per pixel. */
590 if (best < 0)
591 best = i;
592 else if (color_modes[i].color_bits < color_modes[best].color_bits)
593 best = i;
594 else if (color_modes[i].color_bits == color_modes[best].color_bits)
596 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
597 best = i;
598 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
599 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
600 best = i;
605 if (best < 0)
607 /* Couldn't find a match. Return last one that renderer supports. */
608 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
610 if (modes & color_modes[i].mode)
611 return i;
615 return best;
619 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
620 CFMutableSetRef pixel_format_set)
622 CGLPixelFormatAttribute attribs[64] = {
623 kCGLPFAMinimumPolicy,
624 kCGLPFAClosestPolicy,
625 kCGLPFARendererID, renderer.renderer_id,
626 kCGLPFASingleRenderer,
628 int n = 5, n_stack[16], n_stack_idx = -1;
629 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
630 new_pixel_formats = 0;
631 pixel_format request;
632 unsigned int double_buffer;
633 unsigned int accelerated = renderer.accelerated;
635 if (accelerated)
637 attribs[n++] = kCGLPFAAccelerated;
638 attribs[n++] = kCGLPFANoRecovery;
640 else if (!allow_software_rendering)
642 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
643 return;
646 n_stack[++n_stack_idx] = n;
647 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
649 unsigned int aux;
651 n = n_stack[n_stack_idx];
653 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
654 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
655 continue;
657 if (double_buffer)
658 attribs[n++] = kCGLPFADoubleBuffer;
659 memset(&request, 0, sizeof(request));
660 request.accelerated = accelerated;
661 request.double_buffer = double_buffer;
663 /* Don't bother with in-between aux buffers values: either 0 or max. */
664 n_stack[++n_stack_idx] = n;
665 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
667 unsigned int color_mode;
669 n = n_stack[n_stack_idx];
671 attribs[n++] = kCGLPFAAuxBuffers;
672 attribs[n++] = aux;
673 request.aux_buffers = aux;
675 n_stack[++n_stack_idx] = n;
676 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
678 unsigned int depth_mode;
680 n = n_stack[n_stack_idx];
682 if (!(renderer.color_modes & color_modes[color_mode].mode))
683 continue;
685 attribs[n++] = kCGLPFAColorSize;
686 attribs[n++] = color_modes[color_mode].color_bits;
687 attribs[n++] = kCGLPFAAlphaSize;
688 attribs[n++] = color_modes[color_mode].alpha_bits;
689 if (color_modes[color_mode].is_float)
690 attribs[n++] = kCGLPFAColorFloat;
691 request.color_mode = color_mode;
693 n_stack[++n_stack_idx] = n;
694 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
696 unsigned int stencil_mode;
698 n = n_stack[n_stack_idx];
700 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
701 continue;
703 attribs[n++] = kCGLPFADepthSize;
704 attribs[n++] = depth_stencil_modes[depth_mode].bits;
705 request.depth_bits = depth_stencil_modes[depth_mode].bits;
707 n_stack[++n_stack_idx] = n;
708 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
710 unsigned int stereo;
712 n = n_stack[n_stack_idx];
714 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
715 continue;
716 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
717 continue;
719 attribs[n++] = kCGLPFAStencilSize;
720 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
721 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
723 /* FIXME: Could trim search space a bit here depending on GPU.
724 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
725 n_stack[++n_stack_idx] = n;
726 for (stereo = 0; stereo <= 1; stereo++)
728 int accum_mode;
730 n = n_stack[n_stack_idx];
732 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
733 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
734 continue;
736 if (stereo)
737 attribs[n++] = kCGLPFAStereo;
738 request.stereo = stereo;
740 /* Starts at -1 for a 0 accum size */
741 n_stack[++n_stack_idx] = n;
742 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
744 unsigned int target_pass;
746 n = n_stack[n_stack_idx];
748 if (accum_mode >= 0)
750 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
751 continue;
753 attribs[n++] = kCGLPFAAccumSize;
754 attribs[n++] = color_modes[accum_mode].color_bits;
755 request.accum_mode = accum_mode + 1;
757 else
758 request.accum_mode = 0;
760 /* Targets to request are:
761 accelerated: window OR window + pbuffer
762 software: window + pbuffer */
763 n_stack[++n_stack_idx] = n;
764 for (target_pass = 0; target_pass <= accelerated; target_pass++)
766 unsigned int samples, max_samples;
768 n = n_stack[n_stack_idx];
770 attribs[n++] = kCGLPFAWindow;
771 request.window = 1;
773 if (!accelerated || target_pass > 0)
775 attribs[n++] = kCGLPFAPBuffer;
776 request.pbuffer = 1;
778 else
779 request.pbuffer = 0;
781 /* FIXME: Could trim search space a bit here depending on GPU.
782 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
783 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
784 n_stack[++n_stack_idx] = n;
785 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
786 for (samples = 1; samples <= max_samples; samples *= 2)
788 unsigned int backing_store, min_backing_store, max_backing_store;
790 n = n_stack[n_stack_idx];
792 if (samples > 1)
794 attribs[n++] = kCGLPFASampleBuffers;
795 attribs[n++] = renderer.max_sample_buffers;
796 attribs[n++] = kCGLPFASamples;
797 attribs[n++] = samples;
798 request.sample_buffers = renderer.max_sample_buffers;
799 request.samples = samples;
801 else
802 request.sample_buffers = request.samples = 0;
804 if (renderer.backing_store && double_buffer)
806 /* The software renderer seems to always preserve the backing store, whether
807 we ask for it or not. So don't bother not asking for it. */
808 min_backing_store = accelerated ? 0 : 1;
809 max_backing_store = 1;
811 else
812 min_backing_store = max_backing_store = 0;
813 n_stack[++n_stack_idx] = n;
814 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
816 CGLPixelFormatObj pix;
817 GLint virtualScreens;
818 CGLError err;
820 n = n_stack[n_stack_idx];
822 if (backing_store)
823 attribs[n++] = kCGLPFABackingStore;
824 request.backing_store = backing_store;
826 attribs[n] = 0;
828 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
829 if (err == kCGLNoError && pix)
831 pixel_format pf;
832 GLint value, color_size, alpha_size, color_float;
833 UInt64 pf_code;
834 CFNumberRef code_object;
835 BOOL dupe;
837 memset(&pf, 0, sizeof(pf));
839 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
840 pf.accelerated = value;
841 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
842 pf.aux_buffers = value;
843 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
844 pf.depth_bits = value;
845 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
846 pf.double_buffer = value;
847 if (pf.double_buffer &&
848 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
849 pf.backing_store = value;
850 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
851 pf.pbuffer = value;
852 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
853 pf.sample_buffers = value;
854 if (pf.sample_buffers &&
855 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
856 pf.samples = value;
857 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
858 pf.stencil_bits = value;
859 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
860 pf.stereo = value;
861 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
862 pf.window = value;
864 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
865 color_size = 0;
866 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
867 alpha_size = 0;
868 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
869 color_float = 0;
870 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
872 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
873 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
875 CGLReleasePixelFormat(pix);
877 pf_code = code_for_pixel_format(&pf);
879 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
880 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
881 dupe_pixel_formats++;
882 else
884 CFSetAddValue(pixel_format_set, code_object);
885 CFArrayAppendValue(pixel_format_array, code_object);
886 new_pixel_formats++;
888 CFRelease(code_object);
890 if (pf_code == code_for_pixel_format(&request))
891 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
892 else
894 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
895 dupe ? " (duplicate)" : "");
898 else
900 failed_pixel_formats++;
901 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
904 tried_pixel_formats++;
907 n_stack_idx--;
910 n_stack_idx--;
913 n_stack_idx--;
916 n_stack_idx--;
919 n_stack_idx--;
922 n_stack_idx--;
925 n_stack_idx--;
928 n_stack_idx--;
931 n_stack_idx--;
934 n_stack_idx--;
936 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
937 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
938 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
939 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
943 /* The docs for WGL_ARB_pixel_format say:
944 Indices are assigned to pixel formats in the following order:
945 1. Accelerated pixel formats that are displayable
946 2. Accelerated pixel formats that are displayable and which have
947 extended attributes
948 3. Generic pixel formats
949 4. Accelerated pixel formats that are non displayable
951 static int pixel_format_category(pixel_format pf)
953 /* non-displayable */
954 if (!pf.window)
955 return 4;
957 /* non-accelerated a.k.a. software a.k.a. generic */
958 if (!pf.accelerated)
959 return 3;
961 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
962 if (color_modes[pf.color_mode].is_float)
963 return 2;
965 /* accelerated, displayable, no extended attributes */
966 return 1;
970 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
972 CFNumberRef number1 = val1;
973 CFNumberRef number2 = val2;
974 UInt64 code1, code2;
975 pixel_format pf1, pf2;
976 int category1, category2;
978 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
979 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
980 pf1 = pixel_format_for_code(code1);
981 pf2 = pixel_format_for_code(code2);
982 category1 = pixel_format_category(pf1);
983 category2 = pixel_format_category(pf2);
985 if (category1 < category2)
986 return kCFCompareLessThan;
987 if (category1 > category2)
988 return kCFCompareGreaterThan;
990 /* Within a category, sort the "best" formats toward the front since that's
991 what wglChoosePixelFormatARB() has to do. The ordering implemented here
992 matches at least one Windows 7 machine's behavior.
994 /* Accelerated before unaccelerated. */
995 if (pf1.accelerated && !pf2.accelerated)
996 return kCFCompareLessThan;
997 if (!pf1.accelerated && pf2.accelerated)
998 return kCFCompareGreaterThan;
1000 /* Explicit color mode ordering. */
1001 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1002 return kCFCompareLessThan;
1003 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1004 return kCFCompareGreaterThan;
1006 /* Non-pbuffer-capable before pbuffer-capable. */
1007 if (!pf1.pbuffer && pf2.pbuffer)
1008 return kCFCompareLessThan;
1009 if (pf1.pbuffer && !pf2.pbuffer)
1010 return kCFCompareGreaterThan;
1012 /* Fewer samples before more samples. */
1013 if (pf1.samples < pf2.samples)
1014 return kCFCompareLessThan;
1015 if (pf1.samples > pf2.samples)
1016 return kCFCompareGreaterThan;
1018 /* Monoscopic before stereoscopic. (This is a guess.) */
1019 if (!pf1.stereo && pf2.stereo)
1020 return kCFCompareLessThan;
1021 if (pf1.stereo && !pf2.stereo)
1022 return kCFCompareGreaterThan;
1024 /* Single buffered before double buffered. */
1025 if (!pf1.double_buffer && pf2.double_buffer)
1026 return kCFCompareLessThan;
1027 if (pf1.double_buffer && !pf2.double_buffer)
1028 return kCFCompareGreaterThan;
1030 /* Possibly-optimized double buffering before backing-store-preserving
1031 double buffering. */
1032 if (!pf1.backing_store && pf2.backing_store)
1033 return kCFCompareLessThan;
1034 if (pf1.backing_store && !pf2.backing_store)
1035 return kCFCompareGreaterThan;
1037 /* Bigger depth buffer before smaller depth buffer. */
1038 if (pf1.depth_bits > pf2.depth_bits)
1039 return kCFCompareLessThan;
1040 if (pf1.depth_bits < pf2.depth_bits)
1041 return kCFCompareGreaterThan;
1043 /* Smaller stencil buffer before bigger stencil buffer. */
1044 if (pf1.stencil_bits < pf2.stencil_bits)
1045 return kCFCompareLessThan;
1046 if (pf1.stencil_bits > pf2.stencil_bits)
1047 return kCFCompareGreaterThan;
1049 /* Smaller alpha bits before larger alpha bits. */
1050 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1051 return kCFCompareLessThan;
1052 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1053 return kCFCompareGreaterThan;
1055 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1056 if (pf1.accum_mode)
1058 if (pf2.accum_mode)
1060 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1061 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1062 return kCFCompareLessThan;
1063 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1064 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1065 return kCFCompareGreaterThan;
1067 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1068 return kCFCompareLessThan;
1069 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1070 return kCFCompareGreaterThan;
1072 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1073 return kCFCompareLessThan;
1074 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1075 return kCFCompareGreaterThan;
1077 else
1078 return kCFCompareGreaterThan;
1080 else if (pf2.accum_mode)
1081 return kCFCompareLessThan;
1083 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1084 if (pf1.aux_buffers < pf2.aux_buffers)
1085 return kCFCompareLessThan;
1086 if (pf1.aux_buffers > pf2.aux_buffers)
1087 return kCFCompareGreaterThan;
1089 /* If we get here, arbitrarily sort based on code. */
1090 if (code1 < code2)
1091 return kCFCompareLessThan;
1092 if (code1 > code2)
1093 return kCFCompareGreaterThan;
1094 return kCFCompareEqualTo;
1098 static BOOL init_pixel_formats(void)
1100 BOOL ret = FALSE;
1101 CGLRendererInfoObj renderer_info;
1102 GLint rendererCount;
1103 CGLError err;
1104 CFMutableSetRef pixel_format_set;
1105 CFMutableArrayRef pixel_format_array;
1106 int i;
1107 CFRange range;
1109 TRACE("()\n");
1111 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1112 if (err)
1114 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1115 return FALSE;
1118 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1119 if (!pixel_format_set)
1121 WARN("CFSetCreateMutable failed\n");
1122 CGLDestroyRendererInfo(renderer_info);
1123 return FALSE;
1126 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1127 if (!pixel_format_array)
1129 WARN("CFArrayCreateMutable failed\n");
1130 CFRelease(pixel_format_set);
1131 CGLDestroyRendererInfo(renderer_info);
1132 return FALSE;
1135 for (i = 0; i < rendererCount; i++)
1137 renderer_properties renderer;
1139 get_renderer_properties(renderer_info, i, &renderer);
1140 if (TRACE_ON(wgl))
1142 TRACE("renderer_properties %d:\n", i);
1143 dump_renderer(&renderer);
1146 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1149 CFRelease(pixel_format_set);
1150 CGLDestroyRendererInfo(renderer_info);
1152 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1153 if (range.length)
1155 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1156 if (pixel_formats)
1158 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1159 for (i = 0; i < range.length; i++)
1161 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1162 UInt64 code;
1164 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1165 pixel_formats[i] = pixel_format_for_code(code);
1166 if (pixel_formats[i].window)
1167 nb_displayable_formats++;
1170 nb_formats = range.length;
1171 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1172 ret = TRUE;
1174 else
1175 WARN("failed to allocate pixel format list\n");
1177 else
1178 WARN("got no pixel formats\n");
1180 CFRelease(pixel_format_array);
1181 return ret;
1185 static inline BOOL is_valid_pixel_format(int format)
1187 return format > 0 && format <= nb_formats;
1191 static inline BOOL is_displayable_pixel_format(int format)
1193 return format > 0 && format <= nb_displayable_formats;
1197 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1199 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1200 * format in case of probing the number of pixel formats.
1202 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1204 TRACE("Returning format %d\n", format);
1205 return &pixel_formats[format - 1];
1207 return NULL;
1211 static BOOL init_gl_info(void)
1213 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1214 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1216 CGDirectDisplayID display = CGMainDisplayID();
1217 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1218 CGLPixelFormatAttribute attribs[] = {
1219 kCGLPFADisplayMask, displayMask,
1222 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1223 CGLPixelFormatAttribute core_attribs[] =
1225 kCGLPFADisplayMask, displayMask,
1226 kCGLPFAAccelerated,
1227 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1230 #endif
1231 CGLPixelFormatObj pix;
1232 GLint virtualScreens;
1233 CGLError err;
1234 CGLContextObj context;
1235 CGLContextObj old_context = CGLGetCurrentContext();
1236 const char *str;
1237 size_t length;
1239 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1240 if (err != kCGLNoError || !pix)
1242 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1243 return FALSE;
1246 err = CGLCreateContext(pix, NULL, &context);
1247 CGLReleasePixelFormat(pix);
1248 if (err != kCGLNoError || !context)
1250 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1251 return FALSE;
1254 err = CGLSetCurrentContext(context);
1255 if (err != kCGLNoError)
1257 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1258 CGLReleaseContext(context);
1259 return FALSE;
1262 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1263 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1264 strcpy(gl_info.glVersion, str);
1265 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1266 length = strlen(str) + sizeof(legacy_extensions);
1267 if (allow_vsync)
1268 length += strlen(legacy_ext_swap_control);
1269 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1270 strcpy(gl_info.glExtensions, str);
1271 strcat(gl_info.glExtensions, legacy_extensions);
1272 if (allow_vsync)
1273 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1275 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1277 TRACE("GL version : %s\n", gl_info.glVersion);
1278 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1279 sscanf(gl_info.glVersion, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1281 CGLSetCurrentContext(old_context);
1282 CGLReleaseContext(context);
1284 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1285 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1286 if (err != kCGLNoError || !pix)
1288 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1289 err, CGLErrorString(err));
1290 return TRUE;
1293 err = CGLCreateContext(pix, NULL, &context);
1294 CGLReleasePixelFormat(pix);
1295 if (err != kCGLNoError || !context)
1297 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1298 err, CGLErrorString(err));
1299 return TRUE;
1302 err = CGLSetCurrentContext(context);
1303 if (err != kCGLNoError)
1305 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1306 err, CGLErrorString(err));
1307 CGLReleaseContext(context);
1308 return TRUE;
1311 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1312 TRACE("Core context GL version: %s\n", str);
1313 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1314 CGLSetCurrentContext(old_context);
1315 CGLReleaseContext(context);
1316 #endif
1318 return TRUE;
1322 static int get_dc_pixel_format(HDC hdc)
1324 int format;
1325 HWND hwnd;
1327 if ((hwnd = WindowFromDC(hdc)))
1329 struct macdrv_win_data *data;
1331 if (!(data = get_win_data(hwnd)))
1333 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1334 return 0;
1337 format = data->pixel_format;
1338 release_win_data(data);
1340 else
1342 struct wgl_pbuffer *pbuffer;
1344 EnterCriticalSection(&dc_pbuffers_section);
1345 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1346 if (pbuffer)
1347 format = pbuffer->format;
1348 else
1350 WARN("no window or pbuffer for DC %p\n", hdc);
1351 format = 0;
1353 LeaveCriticalSection(&dc_pbuffers_section);
1356 return format;
1360 /**********************************************************************
1361 * create_context
1363 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1365 const pixel_format *pf;
1366 CGLPixelFormatAttribute attribs[64];
1367 int n = 0;
1368 CGLPixelFormatObj pix;
1369 GLint virtualScreens;
1370 CGLError err;
1371 BOOL core = major >= 3;
1373 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1374 if (core)
1376 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1377 return FALSE;
1379 #endif
1381 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1382 if (!pf)
1384 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1385 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1386 return FALSE;
1389 attribs[n++] = kCGLPFAMinimumPolicy;
1390 attribs[n++] = kCGLPFAClosestPolicy;
1392 if (pf->accelerated)
1394 attribs[n++] = kCGLPFAAccelerated;
1395 attribs[n++] = kCGLPFANoRecovery;
1397 else
1399 attribs[n++] = kCGLPFARendererID;
1400 attribs[n++] = kCGLRendererGenericFloatID;
1403 if (pf->double_buffer)
1404 attribs[n++] = kCGLPFADoubleBuffer;
1406 if (!core)
1408 attribs[n++] = kCGLPFAAuxBuffers;
1409 attribs[n++] = pf->aux_buffers;
1412 attribs[n++] = kCGLPFAColorSize;
1413 attribs[n++] = color_modes[pf->color_mode].color_bits;
1414 attribs[n++] = kCGLPFAAlphaSize;
1415 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1416 if (color_modes[pf->color_mode].is_float)
1417 attribs[n++] = kCGLPFAColorFloat;
1419 attribs[n++] = kCGLPFADepthSize;
1420 attribs[n++] = pf->depth_bits;
1422 attribs[n++] = kCGLPFAStencilSize;
1423 attribs[n++] = pf->stencil_bits;
1425 if (pf->stereo)
1426 attribs[n++] = kCGLPFAStereo;
1428 if (pf->accum_mode && !core)
1430 attribs[n++] = kCGLPFAAccumSize;
1431 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1434 if (pf->pbuffer && !core)
1435 attribs[n++] = kCGLPFAPBuffer;
1437 if (pf->sample_buffers && pf->samples)
1439 attribs[n++] = kCGLPFASampleBuffers;
1440 attribs[n++] = pf->sample_buffers;
1441 attribs[n++] = kCGLPFASamples;
1442 attribs[n++] = pf->samples;
1445 if (pf->backing_store)
1446 attribs[n++] = kCGLPFABackingStore;
1448 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1449 if (core)
1451 attribs[n++] = kCGLPFAOpenGLProfile;
1452 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1453 if (major == 3)
1454 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1455 else
1456 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1457 #else
1458 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1459 #endif
1461 #endif
1463 attribs[n] = 0;
1465 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1466 if (err != kCGLNoError || !pix)
1468 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1469 SetLastError(ERROR_INVALID_OPERATION);
1470 return FALSE;
1473 err = CGLCreateContext(pix, share, &context->cglcontext);
1474 CGLReleasePixelFormat(pix);
1475 if (err != kCGLNoError || !context->cglcontext)
1477 context->cglcontext = NULL;
1478 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1479 SetLastError(ERROR_INVALID_OPERATION);
1480 return FALSE;
1483 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1485 GLint opacity = 0;
1486 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1487 if (err != kCGLNoError)
1488 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1490 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1492 GLint order = -1;
1493 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1494 if (err != kCGLNoError)
1495 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1498 context->context = macdrv_create_opengl_context(context->cglcontext);
1499 CGLReleaseContext(context->cglcontext);
1500 if (!context->context)
1502 WARN("macdrv_create_opengl_context() failed\n");
1503 SetLastError(ERROR_INVALID_OPERATION);
1504 return FALSE;
1506 context->major = major;
1508 if (allow_vsync)
1509 InterlockedExchange(&context->update_swap_interval, TRUE);
1511 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1513 return TRUE;
1517 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1519 BOOL ret = TRUE;
1520 *rect = data->client_rect;
1522 if (data->cocoa_window)
1524 if (window)
1525 *window = data->cocoa_window;
1526 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1528 else
1530 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1531 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1532 struct macdrv_win_data *top_data = get_win_data(top);
1534 if (top_data && top_data->cocoa_window)
1536 if (window)
1537 *window = top_data->cocoa_window;
1538 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1539 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1541 else
1542 ret = FALSE;
1544 release_win_data(top_data);
1547 return ret;
1551 /***********************************************************************
1552 * set_win_format
1554 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1556 TRACE("hwnd %p format %d\n", data->hwnd, format);
1558 if (!data->gl_view)
1560 macdrv_window cocoa_window;
1562 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1564 ERR("no top-level parent with Cocoa window in this process\n");
1565 return FALSE;
1568 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1569 if (!data->gl_view)
1571 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1572 return FALSE;
1575 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1576 wine_dbgstr_rect(&data->gl_rect));
1579 data->pixel_format = format;
1581 return TRUE;
1585 /**********************************************************************
1586 * set_pixel_format
1588 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1590 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1592 struct macdrv_win_data *data;
1593 const pixel_format *pf;
1594 HWND hwnd = WindowFromDC(hdc);
1595 BOOL ret = FALSE;
1597 TRACE("hdc %p format %d\n", hdc, fmt);
1599 if (!hwnd || hwnd == GetDesktopWindow())
1601 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1602 return FALSE;
1605 if (!(data = get_win_data(hwnd)))
1607 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1608 return FALSE;
1611 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1613 ret = (data->pixel_format == fmt);
1614 goto done;
1617 /* Check if fmt is in our list of supported formats to see if it is supported. */
1618 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1619 if (!pf)
1621 ERR("Invalid pixel format: %d\n", fmt);
1622 goto done;
1625 if (!pf->window)
1627 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1628 goto done;
1631 if (!set_win_format(data, fmt))
1633 WARN("Couldn't set format of the window, returning failure\n");
1634 goto done;
1637 TRACE("pixel format:\n");
1638 TRACE(" window: %u\n", (unsigned int)pf->window);
1639 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1640 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1641 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1642 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1643 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1644 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1645 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1646 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1647 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1648 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1649 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1650 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1651 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1652 ret = TRUE;
1654 done:
1655 release_win_data(data);
1656 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) __wine_set_pixel_format(hwnd, fmt);
1657 return ret;
1661 /**********************************************************************
1662 * set_gl_view_parent
1664 void set_gl_view_parent(HWND hwnd, HWND parent)
1666 struct macdrv_win_data *data;
1668 if (!(data = get_win_data(hwnd))) return;
1670 if (data->gl_view)
1672 macdrv_window cocoa_window;
1674 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1676 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1678 ERR("no top-level parent with Cocoa window in this process\n");
1679 macdrv_dispose_view(data->gl_view);
1680 data->gl_view = NULL;
1681 release_win_data(data);
1682 __wine_set_pixel_format( hwnd, 0 );
1683 return;
1686 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1689 release_win_data(data);
1693 /**********************************************************************
1694 * make_context_current
1696 static void make_context_current(struct wgl_context *context, BOOL read)
1698 macdrv_view view;
1699 struct wgl_pbuffer *pbuffer;
1701 if (read)
1703 view = context->read_view;
1704 pbuffer = context->read_pbuffer;
1706 else
1708 view = context->draw_view;
1709 pbuffer = context->draw_pbuffer;
1712 if (view || !pbuffer)
1713 macdrv_make_context_current(context->context, view);
1714 else
1716 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1717 pbuffer->level, 0);
1718 CGLSetCurrentContext(context->cglcontext);
1723 /**********************************************************************
1724 * set_swap_interval
1726 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1728 CGLError err;
1730 /* In theory, for single-buffered contexts, there's no such thing as a swap
1731 so the swap interval shouldn't matter. But OS X will synchronize flushes
1732 of single-buffered contexts if the interval is set to non-zero. */
1733 if (interval && !pixel_formats[context->format - 1].double_buffer)
1734 interval = 0;
1736 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1737 if (err != kCGLNoError)
1738 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1740 return err == kCGLNoError;
1744 /**********************************************************************
1745 * sync_swap_interval
1747 static void sync_swap_interval(struct wgl_context *context)
1749 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1751 int interval;
1753 if (context->draw_hwnd)
1755 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1756 if (data)
1758 interval = data->swap_interval;
1759 release_win_data(data);
1761 else /* window was destroyed? */
1762 interval = 1;
1764 else /* pbuffer */
1765 interval = 0;
1767 set_swap_interval(context, interval);
1772 /**********************************************************************
1773 * macdrv_glCopyColorTable
1775 * Hook into glCopyColorTable as part of the implementation of
1776 * wglMakeContextCurrentARB. If the context has a separate readable,
1777 * temporarily make that current, do glCopyColorTable, and then set it
1778 * back to the drawable. This is modeled after what Mesa GLX's Apple
1779 * implementation does.
1781 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1782 GLsizei width)
1784 struct wgl_context *context = NtCurrentTeb()->glContext;
1786 if (context->read_view || context->read_pbuffer)
1787 make_context_current(context, TRUE);
1789 pglCopyColorTable(target, internalformat, x, y, width);
1791 if (context->read_view || context->read_pbuffer)
1792 make_context_current(context, FALSE);
1796 /**********************************************************************
1797 * macdrv_glCopyPixels
1799 * Hook into glCopyPixels as part of the implementation of
1800 * wglMakeContextCurrentARB. If the context has a separate readable,
1801 * temporarily make that current, do glCopyPixels, and then set it back
1802 * to the drawable. This is modeled after what Mesa GLX's Apple
1803 * implementation does.
1805 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1807 struct wgl_context *context = NtCurrentTeb()->glContext;
1809 if (context->read_view || context->read_pbuffer)
1810 make_context_current(context, TRUE);
1812 pglCopyPixels(x, y, width, height, type);
1814 if (context->read_view || context->read_pbuffer)
1815 make_context_current(context, FALSE);
1819 /**********************************************************************
1820 * macdrv_glFinish
1822 static void macdrv_glFinish(void)
1824 struct wgl_context *context = NtCurrentTeb()->glContext;
1826 sync_swap_interval(context);
1827 pglFinish();
1831 /**********************************************************************
1832 * macdrv_glFlush
1834 static void macdrv_glFlush(void)
1836 struct wgl_context *context = NtCurrentTeb()->glContext;
1838 sync_swap_interval(context);
1840 if (skip_single_buffer_flushes)
1842 const pixel_format *pf = &pixel_formats[context->format - 1];
1843 DWORD now = GetTickCount();
1845 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1846 context->last_flush_time, now);
1847 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1849 TRACE("calling glFlushRenderAPPLE()\n");
1850 pglFlushRenderAPPLE();
1851 return;
1853 else
1855 TRACE("calling glFlush()\n");
1856 context->last_flush_time = now;
1860 pglFlush();
1864 /**********************************************************************
1865 * macdrv_glGetString
1867 * Hook into glGetString in order to return some legacy WGL extensions
1868 * that couldn't be advertised via the standard
1869 * WGL_ARB_extensions_string mechanism. Some programs, especially
1870 * older ones, expect to find certain older extensions, such as
1871 * WGL_EXT_extensions_string itself, in the standard GL extensions
1872 * string, and won't query any other WGL extensions unless they find
1873 * that particular extension there.
1875 static const GLubyte *macdrv_glGetString(GLenum name)
1877 if (name == GL_EXTENSIONS && gl_info.glExtensions)
1878 return (const GLubyte *)gl_info.glExtensions;
1879 else
1880 return pglGetString(name);
1884 /**********************************************************************
1885 * macdrv_glReadPixels
1887 * Hook into glReadPixels as part of the implementation of
1888 * wglMakeContextCurrentARB. If the context has a separate readable,
1889 * temporarily make that current, do glReadPixels, and then set it back
1890 * to the drawable. This is modeled after what Mesa GLX's Apple
1891 * implementation does.
1893 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1894 GLenum format, GLenum type, void *pixels)
1896 struct wgl_context *context = NtCurrentTeb()->glContext;
1898 if (context->read_view || context->read_pbuffer)
1899 make_context_current(context, TRUE);
1901 pglReadPixels(x, y, width, height, format, type, pixels);
1903 if (context->read_view || context->read_pbuffer)
1904 make_context_current(context, FALSE);
1908 /**********************************************************************
1909 * macdrv_glViewport
1911 * Hook into glViewport as an opportunity to update the OpenGL context
1912 * if necessary. This is modeled after what Mesa GLX's Apple
1913 * implementation does.
1915 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1917 struct wgl_context *context = NtCurrentTeb()->glContext;
1919 macdrv_update_opengl_context(context->context);
1920 pglViewport(x, y, width, height);
1924 /***********************************************************************
1925 * macdrv_wglBindTexImageARB
1927 * WGL_ARB_render_texture: wglBindTexImageARB
1929 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1931 struct wgl_context *context = NtCurrentTeb()->glContext;
1932 GLenum source;
1933 CGLError err;
1935 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1937 if (pbuffer->no_texture)
1939 SetLastError(ERROR_INVALID_OPERATION);
1940 return GL_FALSE;
1943 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1944 opengl_funcs.gl.p_glFlush();
1946 switch (iBuffer)
1948 case WGL_FRONT_LEFT_ARB:
1949 if (pixel_formats[pbuffer->format - 1].stereo)
1950 source = GL_FRONT_LEFT;
1951 else
1952 source = GL_FRONT;
1953 break;
1954 case WGL_FRONT_RIGHT_ARB:
1955 source = GL_FRONT_RIGHT;
1956 break;
1957 case WGL_BACK_LEFT_ARB:
1958 if (pixel_formats[pbuffer->format - 1].stereo)
1959 source = GL_BACK_LEFT;
1960 else
1961 source = GL_BACK;
1962 break;
1963 case WGL_BACK_RIGHT_ARB:
1964 source = GL_BACK_RIGHT;
1965 break;
1966 case WGL_AUX0_ARB: source = GL_AUX0; break;
1967 case WGL_AUX1_ARB: source = GL_AUX1; break;
1968 case WGL_AUX2_ARB: source = GL_AUX2; break;
1969 case WGL_AUX3_ARB: source = GL_AUX3; break;
1971 case WGL_AUX4_ARB:
1972 case WGL_AUX5_ARB:
1973 case WGL_AUX6_ARB:
1974 case WGL_AUX7_ARB:
1975 case WGL_AUX8_ARB:
1976 case WGL_AUX9_ARB:
1977 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1978 SetLastError(ERROR_INVALID_DATA);
1979 return GL_FALSE;
1981 default:
1982 WARN("unknown source buffer 0x%x\n", iBuffer);
1983 SetLastError(ERROR_INVALID_DATA);
1984 return GL_FALSE;
1987 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1988 if (err != kCGLNoError)
1990 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1991 SetLastError(ERROR_INVALID_OPERATION);
1992 return GL_FALSE;
1995 return GL_TRUE;
1999 /***********************************************************************
2000 * macdrv_wglChoosePixelFormatARB
2002 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2004 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2005 const FLOAT *pfAttribFList, UINT nMaxFormats,
2006 int *piFormats, UINT *nNumFormats)
2008 pixel_format pf, valid;
2009 const int *iptr;
2010 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2011 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2012 int float_color;
2013 BOOL srgb;
2014 int i, found = 0;
2016 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2017 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2018 if (pfAttribFList)
2019 FIXME("unused pfAttribFList\n");
2021 memset(&pf, 0, sizeof(pf));
2022 memset(&valid, 0, sizeof(valid));
2023 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2024 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2025 float_color = -1;
2026 srgb = FALSE;
2028 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2030 int attr = iptr[0];
2031 int value = iptr[1];
2033 TRACE("%s\n", debugstr_attrib(attr, value));
2035 switch (attr)
2037 case WGL_DRAW_TO_WINDOW_ARB:
2038 if (valid.window && (!pf.window != !value)) goto cant_match;
2039 pf.window = (value != 0);
2040 valid.window = 1;
2041 break;
2043 case WGL_DRAW_TO_BITMAP_ARB:
2044 goto cant_match;
2046 case WGL_ACCELERATION_ARB:
2047 if (value == WGL_FULL_ACCELERATION_ARB)
2048 value = 1;
2049 else if (value == WGL_NO_ACCELERATION_ARB)
2050 value = 0;
2051 else
2052 goto cant_match;
2053 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2054 pf.accelerated = value;
2055 valid.accelerated = 1;
2056 break;
2058 case WGL_NEED_PALETTE_ARB:
2059 case WGL_NEED_SYSTEM_PALETTE_ARB:
2060 case WGL_SWAP_LAYER_BUFFERS_ARB:
2061 if (value) goto cant_match;
2062 break;
2064 case WGL_SWAP_METHOD_ARB:
2065 if (value == WGL_SWAP_COPY_ARB)
2066 value = 1;
2067 else if (value == WGL_SWAP_UNDEFINED_ARB)
2068 value = 0;
2069 else
2070 goto cant_match;
2071 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2072 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2073 pf.backing_store = value;
2074 valid.backing_store = 1;
2075 break;
2077 case WGL_NUMBER_OVERLAYS_ARB:
2078 case WGL_NUMBER_UNDERLAYS_ARB:
2079 if (value) goto cant_match;
2080 break;
2082 case WGL_SHARE_DEPTH_ARB:
2083 case WGL_SHARE_STENCIL_ARB:
2084 case WGL_SHARE_ACCUM_ARB:
2085 /* no effect */
2086 break;
2088 case WGL_SUPPORT_GDI_ARB:
2089 if (value) goto cant_match;
2090 break;
2092 case WGL_SUPPORT_OPENGL_ARB:
2093 if (!value) goto cant_match;
2094 break;
2096 case WGL_DOUBLE_BUFFER_ARB:
2097 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2098 pf.double_buffer = (value != 0);
2099 valid.double_buffer = 1;
2100 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2101 break;
2103 case WGL_STEREO_ARB:
2104 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2105 pf.stereo = (value != 0);
2106 valid.stereo = 1;
2107 break;
2109 case WGL_PIXEL_TYPE_ARB:
2110 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2111 value = 1;
2112 else if (value == WGL_TYPE_RGBA_ARB)
2113 value = 0;
2114 else
2116 /* Mac contexts don't support rendering to unsigned floating
2117 point formats, even if GL_EXT_packed_float is supported.
2118 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2119 goto cant_match;
2121 if (float_color != -1 && float_color != value) goto cant_match;
2122 if (srgb && value) goto cant_match;
2123 float_color = value;
2124 break;
2126 case WGL_COLOR_BITS_ARB:
2127 if (color_bits < value) color_bits = value;
2128 break;
2130 case WGL_RED_BITS_ARB:
2131 if (srgb && value > 8) goto cant_match;
2132 if (red_bits < value) red_bits = value;
2133 break;
2135 case WGL_GREEN_BITS_ARB:
2136 if (srgb && value > 8) goto cant_match;
2137 if (green_bits < value) green_bits = value;
2138 break;
2140 case WGL_BLUE_BITS_ARB:
2141 if (srgb && value > 8) goto cant_match;
2142 if (blue_bits < value) blue_bits = value;
2143 break;
2145 case WGL_ALPHA_BITS_ARB:
2146 if (alpha_bits < value) alpha_bits = value;
2147 break;
2149 case WGL_ACCUM_BITS_ARB:
2150 if (accum_bits < value) accum_bits = value;
2151 break;
2153 case WGL_ACCUM_RED_BITS_ARB:
2154 if (accum_red_bits < value) accum_red_bits = value;
2155 break;
2157 case WGL_ACCUM_GREEN_BITS_ARB:
2158 if (accum_green_bits < value) accum_green_bits = value;
2159 break;
2161 case WGL_ACCUM_BLUE_BITS_ARB:
2162 if (accum_blue_bits < value) accum_blue_bits = value;
2163 break;
2165 case WGL_ACCUM_ALPHA_BITS_ARB:
2166 if (accum_alpha_bits < value) accum_alpha_bits = value;
2167 break;
2169 case WGL_DEPTH_BITS_ARB:
2170 if (value > 255) goto cant_match;
2171 if (pf.depth_bits < value) pf.depth_bits = value;
2172 break;
2174 case WGL_STENCIL_BITS_ARB:
2175 if (value > 255) goto cant_match;
2176 if (pf.stencil_bits < value) pf.stencil_bits = value;
2177 break;
2179 case WGL_AUX_BUFFERS_ARB:
2180 if (value > 7) goto cant_match;
2181 if (pf.aux_buffers < value) pf.aux_buffers = value;
2182 break;
2184 case WGL_SAMPLE_BUFFERS_ARB:
2185 if (value > 1) goto cant_match;
2186 if (pf.sample_buffers < value) pf.sample_buffers = value;
2187 break;
2189 case WGL_SAMPLES_ARB:
2190 if (value > 31) goto cant_match;
2191 if (pf.samples < value) pf.samples = value;
2192 break;
2194 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2195 /* sRGB is only supported for 8-bit integer color components */
2196 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2197 goto cant_match;
2198 srgb = TRUE;
2199 break;
2201 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2202 case WGL_RED_SHIFT_ARB:
2203 case WGL_GREEN_SHIFT_ARB:
2204 case WGL_BLUE_SHIFT_ARB:
2205 case WGL_ALPHA_SHIFT_ARB:
2206 case WGL_TRANSPARENT_ARB:
2207 case WGL_TRANSPARENT_RED_VALUE_ARB:
2208 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2209 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2210 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2211 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2212 /* ignored */
2213 break;
2215 case WGL_DRAW_TO_PBUFFER_ARB:
2216 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2217 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2218 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2219 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2220 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2221 pf.pbuffer = (value != 0);
2222 valid.pbuffer = 1;
2223 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2224 !alpha_bits)
2225 alpha_bits = 1;
2226 break;
2228 default:
2229 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2230 return GL_FALSE;
2234 TRACE("required: w/p/a %s/%s/%s col/r/g/b/a %d%s/%d/%d/%d/%d srgb %d ac %d/%d/%d/%d/%d dp/stn/ax/b/db/str %u/%u/%u/%s/%s/%s samp %u/%u\n",
2235 valid.window ? (pf.window ? "1" : "0") : "?",
2236 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2237 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2238 color_bits,
2239 float_color == -1 ? "?" : float_color ? "f" : "",
2240 red_bits,
2241 green_bits,
2242 blue_bits,
2243 alpha_bits,
2244 (int)srgb,
2245 accum_bits,
2246 accum_red_bits,
2247 accum_green_bits,
2248 accum_blue_bits,
2249 accum_alpha_bits,
2250 pf.depth_bits,
2251 pf.stencil_bits,
2252 pf.aux_buffers,
2253 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2254 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2255 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2256 pf.sample_buffers,
2257 pf.samples);
2259 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2261 const struct color_mode *mode;
2263 if (valid.window && pixel_formats[i].window != pf.window) continue;
2264 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2265 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2266 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2267 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2268 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2270 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2271 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2272 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2273 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2274 if (pixel_formats[i].samples < pf.samples) continue;
2276 mode = &color_modes[pixel_formats[i].color_mode];
2277 /* If the mode doesn't have alpha, check requested color bits against
2278 bits per pixel instead of the mode's color bits. On Windows, color
2279 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2280 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2281 expects that to match such a pixel format, we need to accommodate that. */
2282 if (mode->alpha_bits)
2284 if (mode->color_bits < color_bits)
2285 continue;
2287 else
2289 if (mode->bits_per_pixel < color_bits)
2290 continue;
2292 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2293 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2294 continue;
2295 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2296 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2297 continue;
2299 if (pixel_formats[i].accum_mode)
2301 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2302 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2303 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2304 mode->alpha_bits < accum_alpha_bits)
2305 continue;
2307 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2308 continue;
2310 piFormats[found++] = i + 1;
2311 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2314 cant_match:
2315 *nNumFormats = found;
2317 return TRUE;
2321 /***********************************************************************
2322 * macdrv_wglCreateContextAttribsARB
2324 * WGL_ARB_create_context: wglCreateContextAttribsARB
2326 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2327 struct wgl_context *share_context,
2328 const int *attrib_list)
2330 int format;
2331 struct wgl_context *context;
2332 const int *iptr;
2333 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2334 BOOL core = FALSE;
2336 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2338 format = get_dc_pixel_format(hdc);
2340 if (!is_valid_pixel_format(format))
2342 ERR("Invalid pixel format %d, expect problems!\n", format);
2343 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2344 return NULL;
2347 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2349 int attr = iptr[0];
2350 int value = iptr[1];
2352 TRACE("%s\n", debugstr_attrib(attr, value));
2354 switch (attr)
2356 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2357 major = value;
2358 break;
2360 case WGL_CONTEXT_MINOR_VERSION_ARB:
2361 minor = value;
2362 break;
2364 case WGL_CONTEXT_LAYER_PLANE_ARB:
2365 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2366 break;
2368 case WGL_CONTEXT_FLAGS_ARB:
2369 flags = value;
2370 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2371 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2372 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2373 break;
2375 case WGL_CONTEXT_PROFILE_MASK_ARB:
2376 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2377 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2379 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2380 SetLastError(ERROR_INVALID_PROFILE_ARB);
2381 return NULL;
2383 profile = value;
2384 break;
2386 default:
2387 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2388 SetLastError(ERROR_INVALID_PARAMETER);
2389 return NULL;
2393 if ((major == 3 && (minor == 2 || minor == 3)) ||
2394 (major == 4 && (minor == 0 || minor == 1)))
2396 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2398 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2399 SetLastError(ERROR_INVALID_VERSION_ARB);
2400 return NULL;
2402 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2404 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2405 SetLastError(ERROR_INVALID_PROFILE_ARB);
2406 return NULL;
2408 if (major > gl_info.max_major ||
2409 (major == gl_info.max_major && minor > gl_info.max_minor))
2411 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2412 major, minor);
2413 SetLastError(ERROR_INVALID_PROFILE_ARB);
2414 return NULL;
2416 core = TRUE;
2418 else if (major >= 3)
2420 WARN("Profile version %u.%u not supported\n", major, minor);
2421 SetLastError(ERROR_INVALID_VERSION_ARB);
2422 return NULL;
2424 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2425 (major == 2 && (minor < 0 || minor > 1)))
2427 WARN("Invalid GL version requested\n");
2428 SetLastError(ERROR_INVALID_VERSION_ARB);
2429 return NULL;
2431 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2433 WARN("Forward compatible context requested for GL version < 3\n");
2434 SetLastError(ERROR_INVALID_VERSION_ARB);
2435 return NULL;
2438 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
2440 context->format = format;
2441 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2443 HeapFree(GetProcessHeap(), 0, context);
2444 return NULL;
2447 EnterCriticalSection(&context_section);
2448 list_add_tail(&context_list, &context->entry);
2449 LeaveCriticalSection(&context_section);
2451 return context;
2455 /**********************************************************************
2456 * macdrv_wglCreatePbufferARB
2458 * WGL_ARB_pbuffer: wglCreatePbufferARB
2460 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2461 const int *piAttribList)
2463 struct wgl_pbuffer* pbuffer;
2464 GLenum target = 0;
2465 GLenum internalFormat = 0;
2466 CGLError err;
2468 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2469 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2471 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2473 WARN("invalid pixel format %d\n", iPixelFormat);
2474 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2475 return NULL;
2478 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2479 pbuffer->format = iPixelFormat;
2481 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2483 int attr = piAttribList[0];
2484 int value = piAttribList[1];
2486 switch (attr)
2488 case WGL_PBUFFER_LARGEST_ARB:
2489 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2490 break;
2492 case WGL_TEXTURE_FORMAT_ARB:
2493 switch (value)
2495 case WGL_TEXTURE_RGBA_ARB:
2496 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2497 internalFormat = GL_RGBA;
2498 break;
2499 case WGL_TEXTURE_RGB_ARB:
2500 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2501 internalFormat = GL_RGB;
2502 break;
2503 case WGL_NO_TEXTURE_ARB:
2504 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2505 internalFormat = 0;
2506 break;
2507 default:
2508 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2509 SetLastError(ERROR_INVALID_DATA);
2510 goto done;
2512 break;
2514 case WGL_TEXTURE_TARGET_ARB:
2515 pbuffer->face = 0;
2516 switch (value)
2518 case WGL_NO_TEXTURE_ARB:
2519 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2520 target = 0;
2521 break;
2522 case WGL_TEXTURE_CUBE_MAP_ARB:
2523 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2524 target = GL_TEXTURE_CUBE_MAP;
2525 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2526 break;
2527 case WGL_TEXTURE_1D_ARB:
2528 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2529 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2530 goto done;
2531 case WGL_TEXTURE_2D_ARB:
2532 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2533 target = GL_TEXTURE_2D;
2534 break;
2535 case WGL_TEXTURE_RECTANGLE_NV:
2536 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2537 target = GL_TEXTURE_RECTANGLE;
2538 break;
2539 default:
2540 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2541 SetLastError(ERROR_INVALID_DATA);
2542 goto done;
2544 break;
2546 case WGL_MIPMAP_TEXTURE_ARB:
2547 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2548 pbuffer->max_level = 0;
2549 if (value)
2551 int size = min(iWidth, iHeight) / 2;
2552 while (size)
2554 pbuffer->max_level++;
2555 size /= 2;
2558 break;
2560 default:
2561 WARN("unknown attribute 0x%x\n", attr);
2562 SetLastError(ERROR_INVALID_DATA);
2563 goto done;
2567 if (!target || !internalFormat)
2569 pbuffer->no_texture = TRUE;
2570 /* no actual way to turn off ability to texture; use most permissive target */
2571 target = GL_TEXTURE_RECTANGLE;
2572 internalFormat = GL_RGB;
2575 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2576 if (err != kCGLNoError)
2578 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2579 pbuffer->pbuffer = NULL;
2580 if (err == kCGLBadAlloc)
2581 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2582 else
2583 SetLastError(ERROR_INVALID_DATA);
2586 done:
2587 if (!pbuffer->pbuffer)
2589 HeapFree(GetProcessHeap(), 0, pbuffer);
2590 return NULL;
2593 TRACE(" -> %p\n", pbuffer);
2594 return pbuffer;
2598 /**********************************************************************
2599 * macdrv_wglDestroyPbufferARB
2601 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2603 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2605 TRACE("pbuffer %p\n", pbuffer);
2606 if (pbuffer && pbuffer->pbuffer)
2607 CGLReleasePBuffer(pbuffer->pbuffer);
2608 HeapFree(GetProcessHeap(), 0, pbuffer);
2609 return GL_TRUE;
2613 /**********************************************************************
2614 * macdrv_wglGetExtensionsStringARB
2616 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2618 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
2620 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2621 this can be specific to the CGL renderer like we're supposed to do. */
2622 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2623 return gl_info.wglExtensions;
2627 /**********************************************************************
2628 * macdrv_wglGetExtensionsStringEXT
2630 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2632 static const char *macdrv_wglGetExtensionsStringEXT(void)
2634 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2635 return gl_info.wglExtensions;
2639 /**********************************************************************
2640 * macdrv_wglGetPbufferDCARB
2642 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2644 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2646 HDC hdc;
2647 struct wgl_pbuffer *prev;
2649 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2650 if (!hdc) return 0;
2652 EnterCriticalSection(&dc_pbuffers_section);
2653 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2654 if (prev)
2656 CGLReleasePBuffer(prev->pbuffer);
2657 HeapFree(GetProcessHeap(), 0, prev);
2659 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2660 LeaveCriticalSection(&dc_pbuffers_section);
2662 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2663 return hdc;
2667 /**********************************************************************
2668 * macdrv_wglGetPixelFormatAttribivARB
2670 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2672 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2673 UINT nAttributes, const int *piAttributes, int *piValues)
2675 const pixel_format *pf;
2676 UINT i;
2678 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2679 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2681 if (!nAttributes) return GL_TRUE;
2683 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2685 piValues[0] = nb_formats;
2686 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2687 return GL_TRUE;
2690 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2691 if (!pf)
2693 WARN("invalid pixel format %d\n", iPixelFormat);
2694 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2695 return GL_FALSE;
2698 for (i = 0; i < nAttributes; ++i)
2700 switch (piAttributes[i])
2702 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2703 piValues[i] = nb_formats;
2704 break;
2706 case WGL_DRAW_TO_WINDOW_ARB:
2707 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2708 break;
2710 case WGL_DRAW_TO_BITMAP_ARB:
2711 piValues[i] = GL_FALSE;
2712 break;
2714 case WGL_ACCELERATION_ARB:
2715 if (iLayerPlane) goto invalid_layer;
2716 if (pf->accelerated)
2717 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2718 else
2719 piValues[i] = WGL_NO_ACCELERATION_ARB;
2720 break;
2722 case WGL_NEED_PALETTE_ARB:
2723 case WGL_NEED_SYSTEM_PALETTE_ARB:
2724 case WGL_SWAP_LAYER_BUFFERS_ARB:
2725 piValues[i] = GL_FALSE;
2726 break;
2728 case WGL_SWAP_METHOD_ARB:
2729 if (pf->double_buffer && pf->backing_store)
2730 piValues[i] = WGL_SWAP_COPY_ARB;
2731 else
2732 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2733 break;
2735 case WGL_NUMBER_OVERLAYS_ARB:
2736 case WGL_NUMBER_UNDERLAYS_ARB:
2737 piValues[i] = 0;
2738 break;
2740 case WGL_TRANSPARENT_ARB:
2741 if (iLayerPlane) goto invalid_layer;
2742 piValues[i] = GL_FALSE;
2743 break;
2745 case WGL_TRANSPARENT_RED_VALUE_ARB:
2746 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2747 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2748 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2749 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2750 if (iLayerPlane) goto invalid_layer;
2751 piValues[i] = 0;
2752 break;
2754 case WGL_SHARE_DEPTH_ARB:
2755 case WGL_SHARE_STENCIL_ARB:
2756 case WGL_SHARE_ACCUM_ARB:
2757 if (iLayerPlane) goto invalid_layer;
2758 piValues[i] = GL_TRUE;
2759 break;
2761 case WGL_SUPPORT_GDI_ARB:
2762 if (iLayerPlane) goto invalid_layer;
2763 piValues[i] = GL_FALSE;
2764 break;
2766 case WGL_SUPPORT_OPENGL_ARB:
2767 if (iLayerPlane) goto invalid_layer;
2768 piValues[i] = GL_TRUE;
2769 break;
2771 case WGL_DOUBLE_BUFFER_ARB:
2772 if (iLayerPlane) goto invalid_layer;
2773 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2774 break;
2776 case WGL_STEREO_ARB:
2777 if (iLayerPlane) goto invalid_layer;
2778 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2779 break;
2781 case WGL_PIXEL_TYPE_ARB:
2782 if (iLayerPlane) goto invalid_layer;
2783 if (color_modes[pf->color_mode].is_float)
2784 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2785 else
2786 piValues[i] = WGL_TYPE_RGBA_ARB;
2787 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2788 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2789 However, Mac contexts don't support rendering to unsigned floating-point
2790 formats, even when GL_EXT_packed_float is supported. */
2791 break;
2793 case WGL_COLOR_BITS_ARB:
2794 if (iLayerPlane) goto invalid_layer;
2795 /* If the mode doesn't have alpha, return bits per pixel instead
2796 of color bits. On Windows, color bits sometimes exceeds r+g+b
2797 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2798 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2799 pixel format, we need to accommodate that. */
2800 if (color_modes[pf->color_mode].alpha_bits)
2801 piValues[i] = color_modes[pf->color_mode].color_bits;
2802 else
2803 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2804 break;
2806 case WGL_RED_BITS_ARB:
2807 if (iLayerPlane) goto invalid_layer;
2808 piValues[i] = color_modes[pf->color_mode].red_bits;
2809 break;
2811 case WGL_RED_SHIFT_ARB:
2812 if (iLayerPlane) goto invalid_layer;
2813 piValues[i] = color_modes[pf->color_mode].red_shift;
2814 break;
2816 case WGL_GREEN_BITS_ARB:
2817 if (iLayerPlane) goto invalid_layer;
2818 piValues[i] = color_modes[pf->color_mode].green_bits;
2819 break;
2821 case WGL_GREEN_SHIFT_ARB:
2822 if (iLayerPlane) goto invalid_layer;
2823 piValues[i] = color_modes[pf->color_mode].green_shift;
2824 break;
2826 case WGL_BLUE_BITS_ARB:
2827 if (iLayerPlane) goto invalid_layer;
2828 piValues[i] = color_modes[pf->color_mode].blue_bits;
2829 break;
2831 case WGL_BLUE_SHIFT_ARB:
2832 if (iLayerPlane) goto invalid_layer;
2833 piValues[i] = color_modes[pf->color_mode].blue_shift;
2834 break;
2836 case WGL_ALPHA_BITS_ARB:
2837 if (iLayerPlane) goto invalid_layer;
2838 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2839 break;
2841 case WGL_ALPHA_SHIFT_ARB:
2842 if (iLayerPlane) goto invalid_layer;
2843 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2844 break;
2846 case WGL_ACCUM_BITS_ARB:
2847 if (iLayerPlane) goto invalid_layer;
2848 if (pf->accum_mode)
2849 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2850 else
2851 piValues[i] = 0;
2852 break;
2854 case WGL_ACCUM_RED_BITS_ARB:
2855 if (iLayerPlane) goto invalid_layer;
2856 if (pf->accum_mode)
2857 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2858 else
2859 piValues[i] = 0;
2860 break;
2862 case WGL_ACCUM_GREEN_BITS_ARB:
2863 if (iLayerPlane) goto invalid_layer;
2864 if (pf->accum_mode)
2865 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2866 else
2867 piValues[i] = 0;
2868 break;
2870 case WGL_ACCUM_BLUE_BITS_ARB:
2871 if (iLayerPlane) goto invalid_layer;
2872 if (pf->accum_mode)
2873 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2874 else
2875 piValues[i] = 0;
2876 break;
2878 case WGL_ACCUM_ALPHA_BITS_ARB:
2879 if (iLayerPlane) goto invalid_layer;
2880 if (pf->accum_mode)
2881 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2882 else
2883 piValues[i] = 0;
2884 break;
2886 case WGL_DEPTH_BITS_ARB:
2887 if (iLayerPlane) goto invalid_layer;
2888 piValues[i] = pf->depth_bits;
2889 break;
2891 case WGL_STENCIL_BITS_ARB:
2892 if (iLayerPlane) goto invalid_layer;
2893 piValues[i] = pf->stencil_bits;
2894 break;
2896 case WGL_AUX_BUFFERS_ARB:
2897 if (iLayerPlane) goto invalid_layer;
2898 piValues[i] = pf->aux_buffers;
2899 break;
2901 case WGL_SAMPLE_BUFFERS_ARB:
2902 if (iLayerPlane) goto invalid_layer;
2903 piValues[i] = pf->sample_buffers;
2904 break;
2906 case WGL_SAMPLES_ARB:
2907 if (iLayerPlane) goto invalid_layer;
2908 piValues[i] = pf->samples;
2909 break;
2911 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2912 if (iLayerPlane) goto invalid_layer;
2913 /* sRGB is only supported for 8-bit integer color components */
2914 if (color_modes[pf->color_mode].red_bits == 8 &&
2915 color_modes[pf->color_mode].green_bits == 8 &&
2916 color_modes[pf->color_mode].blue_bits == 8 &&
2917 !color_modes[pf->color_mode].is_float)
2918 piValues[i] = GL_TRUE;
2919 else
2920 piValues[i] = GL_FALSE;
2921 break;
2923 case WGL_DRAW_TO_PBUFFER_ARB:
2924 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2925 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2926 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2927 break;
2929 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2930 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2931 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2932 break;
2934 case WGL_MAX_PBUFFER_WIDTH_ARB:
2935 piValues[i] = gl_info.max_viewport_dims[0];
2936 break;
2938 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2939 piValues[i] = gl_info.max_viewport_dims[1];
2940 break;
2942 case WGL_MAX_PBUFFER_PIXELS_ARB:
2943 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2944 break;
2946 default:
2947 WARN("invalid attribute %x\n", piAttributes[i]);
2948 return GL_FALSE;
2951 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2954 return GL_TRUE;
2956 invalid_layer:
2957 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2958 return GL_FALSE;
2962 /**********************************************************************
2963 * macdrv_wglGetPixelFormatAttribfvARB
2965 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2967 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2968 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2970 int *attr;
2971 int ret;
2973 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2974 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2976 /* Allocate a temporary array to store integer values */
2977 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2978 if (!attr)
2980 ERR("couldn't allocate %d array\n", nAttributes);
2981 return GL_FALSE;
2984 /* Piggy-back on wglGetPixelFormatAttribivARB */
2985 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2986 if (ret)
2988 UINT i;
2990 /* Convert integer values to float. Should also check for attributes
2991 that can give decimal values here */
2992 for (i = 0; i < nAttributes; i++)
2993 pfValues[i] = attr[i];
2996 HeapFree(GetProcessHeap(), 0, attr);
2997 return ret;
3001 /**********************************************************************
3002 * macdrv_wglGetSwapIntervalEXT
3004 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3006 static int macdrv_wglGetSwapIntervalEXT(void)
3008 struct wgl_context *context = NtCurrentTeb()->glContext;
3009 struct macdrv_win_data *data;
3010 long value;
3011 CGLError err;
3013 TRACE("\n");
3015 if ((data = get_win_data(context->draw_hwnd)))
3017 value = data->swap_interval;
3018 release_win_data(data);
3020 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3021 set_swap_interval(context, value);
3023 else
3025 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3026 if (err != kCGLNoError)
3028 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3029 err, CGLErrorString(err));
3030 value = 1;
3034 return value;
3038 /***********************************************************************
3039 * macdrv_wglMakeContextCurrentARB
3041 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3043 * This is not supported directly by OpenGL on the Mac. We emulate it
3044 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3045 * temporarily swap the drawable. This follows the technique used in
3046 * the implementation of Mesa GLX for Apple.
3048 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3050 struct macdrv_win_data *data;
3051 HWND hwnd;
3053 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3054 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3056 if (!context)
3058 macdrv_make_context_current(NULL, NULL);
3059 NtCurrentTeb()->glContext = NULL;
3060 return TRUE;
3063 if ((hwnd = WindowFromDC(draw_hdc)))
3065 if (!(data = get_win_data(hwnd)))
3067 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3068 return FALSE;
3071 if (!data->pixel_format)
3073 WARN("no pixel format set\n");
3074 release_win_data(data);
3075 SetLastError(ERROR_INVALID_HANDLE);
3076 return FALSE;
3078 if (context->format != data->pixel_format)
3080 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3081 release_win_data(data);
3082 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3083 return FALSE;
3086 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
3087 set_swap_interval(context, data->swap_interval);
3089 context->draw_hwnd = hwnd;
3090 context->draw_view = data->gl_view;
3091 context->draw_pbuffer = NULL;
3092 release_win_data(data);
3094 else
3096 struct wgl_pbuffer *pbuffer;
3098 EnterCriticalSection(&dc_pbuffers_section);
3099 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3100 if (pbuffer)
3102 if (context->format != pbuffer->format)
3104 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3105 LeaveCriticalSection(&dc_pbuffers_section);
3106 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3107 return FALSE;
3110 if (allow_vsync &&
3111 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
3112 set_swap_interval(context, 0);
3114 else
3116 WARN("no window or pbuffer for DC\n");
3117 LeaveCriticalSection(&dc_pbuffers_section);
3118 SetLastError(ERROR_INVALID_HANDLE);
3119 return FALSE;
3122 context->draw_hwnd = NULL;
3123 context->draw_view = NULL;
3124 context->draw_pbuffer = pbuffer;
3125 LeaveCriticalSection(&dc_pbuffers_section);
3128 context->read_view = NULL;
3129 context->read_pbuffer = NULL;
3130 if (read_hdc && read_hdc != draw_hdc)
3132 if ((hwnd = WindowFromDC(read_hdc)))
3134 if ((data = get_win_data(hwnd)))
3136 if (data->gl_view != context->draw_view)
3137 context->read_view = data->gl_view;
3138 release_win_data(data);
3141 else
3143 EnterCriticalSection(&dc_pbuffers_section);
3144 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3145 LeaveCriticalSection(&dc_pbuffers_section);
3149 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
3150 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
3152 make_context_current(context, FALSE);
3153 context->has_been_current = TRUE;
3154 NtCurrentTeb()->glContext = context;
3156 return TRUE;
3160 /**********************************************************************
3161 * macdrv_wglQueryPbufferARB
3163 * WGL_ARB_pbuffer: wglQueryPbufferARB
3165 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3167 CGLError err;
3168 GLsizei width;
3169 GLsizei height;
3170 GLenum target;
3171 GLenum internalFormat;
3172 GLint mipmap;
3174 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3176 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3177 if (err != kCGLNoError)
3179 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3180 SetLastError(ERROR_INVALID_HANDLE);
3181 return GL_FALSE;
3184 switch (iAttribute)
3186 case WGL_PBUFFER_WIDTH_ARB:
3187 *piValue = width;
3188 break;
3189 case WGL_PBUFFER_HEIGHT_ARB:
3190 *piValue = height;
3191 break;
3192 case WGL_PBUFFER_LOST_ARB:
3193 /* Mac PBuffers can't be lost */
3194 *piValue = GL_FALSE;
3195 break;
3196 case WGL_TEXTURE_FORMAT_ARB:
3197 if (pbuffer->no_texture)
3198 *piValue = WGL_NO_TEXTURE_ARB;
3199 else switch (internalFormat)
3201 case GL_RGBA:
3202 *piValue = WGL_TEXTURE_RGBA_ARB;
3203 break;
3204 case GL_RGB:
3205 default:
3206 *piValue = WGL_TEXTURE_RGB_ARB;
3207 break;
3209 break;
3210 case WGL_TEXTURE_TARGET_ARB:
3211 if (pbuffer->no_texture)
3212 *piValue = WGL_NO_TEXTURE_ARB;
3213 else switch (target)
3215 case GL_TEXTURE_CUBE_MAP:
3216 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3217 break;
3218 case GL_TEXTURE_2D:
3219 *piValue = WGL_TEXTURE_2D_ARB;
3220 break;
3221 case GL_TEXTURE_RECTANGLE:
3222 default:
3223 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3224 break;
3226 break;
3227 case WGL_MIPMAP_TEXTURE_ARB:
3228 *piValue = (pbuffer->max_level > 0);
3229 break;
3230 case WGL_MIPMAP_LEVEL_ARB:
3231 *piValue = pbuffer->level;
3232 break;
3233 case WGL_CUBE_MAP_FACE_ARB:
3234 switch (pbuffer->face)
3236 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3237 default:
3238 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3239 break;
3240 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3241 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3242 break;
3243 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3244 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3245 break;
3246 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3247 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3248 break;
3249 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3250 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3251 break;
3252 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3253 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3254 break;
3256 break;
3257 default:
3258 WARN("invalid attribute 0x%x\n", iAttribute);
3259 SetLastError(ERROR_INVALID_DATA);
3260 return GL_FALSE;
3263 return GL_TRUE;
3267 /**********************************************************************
3268 * macdrv_wglReleasePbufferDCARB
3270 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3272 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3274 struct wgl_pbuffer *prev;
3276 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3278 EnterCriticalSection(&dc_pbuffers_section);
3280 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3281 if (prev)
3283 if (prev != pbuffer)
3284 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3285 CGLReleasePBuffer(prev->pbuffer);
3286 HeapFree(GetProcessHeap(), 0, prev);
3287 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3289 else hdc = 0;
3291 LeaveCriticalSection(&dc_pbuffers_section);
3293 return hdc && DeleteDC(hdc);
3297 /**********************************************************************
3298 * macdrv_wglReleaseTexImageARB
3300 * WGL_ARB_render_texture: wglReleaseTexImageARB
3302 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3304 struct wgl_context *context = NtCurrentTeb()->glContext;
3305 CGLError err;
3307 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3309 if (pbuffer->no_texture)
3311 SetLastError(ERROR_INVALID_OPERATION);
3312 return GL_FALSE;
3315 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3316 if (err != kCGLNoError)
3318 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3319 SetLastError(ERROR_INVALID_OPERATION);
3320 return GL_FALSE;
3323 return GL_TRUE;
3327 /**********************************************************************
3328 * macdrv_wglSetPbufferAttribARB
3330 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3332 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
3334 struct wgl_context *context = NtCurrentTeb()->glContext;
3336 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
3338 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3340 int attr = piAttribList[0];
3341 int value = piAttribList[1];
3342 switch (attr)
3344 case WGL_MIPMAP_LEVEL_ARB:
3345 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
3346 pbuffer->level = value;
3347 break;
3348 case WGL_CUBE_MAP_FACE_ARB:
3349 switch (value)
3351 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3352 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3353 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3354 break;
3355 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3356 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3357 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
3358 break;
3359 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3360 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
3361 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
3362 break;
3363 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3364 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
3365 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
3366 break;
3367 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3368 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
3369 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
3370 break;
3371 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3372 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
3373 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
3374 break;
3375 default:
3376 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
3377 SetLastError(ERROR_INVALID_DATA);
3378 return GL_FALSE;
3380 break;
3381 default:
3382 WARN("invalide attribute 0x%x\n", attr);
3383 SetLastError(ERROR_INVALID_DATA);
3384 return GL_FALSE;
3388 if (context && context->draw_pbuffer == pbuffer)
3389 make_context_current(context, FALSE);
3391 return GL_TRUE;
3395 /**********************************************************************
3396 * macdrv_wglSetPixelFormatWINE
3398 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3400 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
3402 return set_pixel_format(hdc, fmt, TRUE);
3406 /**********************************************************************
3407 * macdrv_wglSwapIntervalEXT
3409 * WGL_EXT_swap_control: wglSwapIntervalEXT
3411 static BOOL macdrv_wglSwapIntervalEXT(int interval)
3413 struct wgl_context *context = NtCurrentTeb()->glContext;
3414 BOOL changed = FALSE;
3416 TRACE("interval %d\n", interval);
3418 if (interval < 0)
3420 SetLastError(ERROR_INVALID_DATA);
3421 return FALSE;
3423 if (interval > 1)
3424 interval = 1;
3426 if (context->draw_hwnd)
3428 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
3429 if (data)
3431 changed = data->swap_interval != interval;
3432 if (changed)
3433 data->swap_interval = interval;
3434 release_win_data(data);
3437 else /* pbuffer */
3438 interval = 0;
3440 InterlockedExchange(&context->update_swap_interval, FALSE);
3441 if (!set_swap_interval(context, interval))
3443 SetLastError(ERROR_GEN_FAILURE);
3444 return FALSE;
3447 if (changed)
3449 struct wgl_context *ctx;
3451 EnterCriticalSection(&context_section);
3452 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
3454 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
3455 InterlockedExchange(&context->update_swap_interval, TRUE);
3457 LeaveCriticalSection(&context_section);
3460 return TRUE;
3464 static void register_extension(const char *ext)
3466 if (gl_info.wglExtensions[0])
3467 strcat(gl_info.wglExtensions, " ");
3468 strcat(gl_info.wglExtensions, ext);
3470 TRACE("'%s'\n", ext);
3473 static void load_extensions(void)
3476 * ARB Extensions
3478 register_extension("WGL_ARB_extensions_string");
3479 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
3481 register_extension("WGL_ARB_make_current_read");
3482 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
3483 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
3485 register_extension("WGL_ARB_pixel_format");
3486 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
3487 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
3488 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
3490 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
3492 register_extension("WGL_ARB_pixel_format_float");
3493 register_extension("WGL_ATI_pixel_format_float");
3496 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
3497 register_extension("WGL_ARB_multisample");
3499 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3500 register_extension("WGL_ARB_framebuffer_sRGB");
3502 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
3504 register_extension("WGL_ARB_pbuffer");
3505 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
3506 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
3507 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
3508 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
3509 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
3511 register_extension("WGL_ARB_render_texture");
3512 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
3513 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
3514 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
3516 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
3517 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
3518 register_extension("WGL_NV_render_texture_rectangle");
3521 register_extension("WGL_ARB_create_context");
3522 register_extension("WGL_ARB_create_context_profile");
3523 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
3526 * EXT Extensions
3528 register_extension("WGL_EXT_extensions_string");
3529 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
3531 if (allow_vsync)
3533 register_extension("WGL_EXT_swap_control");
3534 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
3535 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
3538 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3539 check for either, so register them separately. */
3540 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3541 register_extension("WGL_EXT_framebuffer_sRGB");
3543 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3544 register_extension("WGL_EXT_pixel_format_packed_float");
3547 * WINE-specific WGL Extensions
3550 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3551 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3553 register_extension("WGL_WINE_pixel_format_passthrough");
3554 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3558 static BOOL init_opengl(void)
3560 static BOOL init_done = FALSE;
3561 unsigned int i;
3562 char buffer[200];
3564 if (init_done) return (opengl_handle != NULL);
3565 init_done = TRUE;
3567 TRACE("()\n");
3569 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3570 if (!dc_pbuffers)
3572 WARN("CFDictionaryCreateMutable failed\n");
3573 return FALSE;
3576 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3577 if (!opengl_handle)
3579 ERR("Failed to load OpenGL: %s\n", buffer);
3580 ERR("OpenGL support is disabled.\n");
3581 return FALSE;
3584 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3586 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3588 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3589 goto failed;
3593 /* redirect some standard OpenGL functions */
3594 #define REDIRECT(func) \
3595 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3596 REDIRECT(glCopyPixels);
3597 REDIRECT(glGetString);
3598 REDIRECT(glReadPixels);
3599 REDIRECT(glViewport);
3600 if (skip_single_buffer_flushes || allow_vsync)
3601 REDIRECT(glFlush);
3602 if (allow_vsync)
3603 REDIRECT(glFinish);
3604 #undef REDIRECT
3606 /* redirect some OpenGL extension functions */
3607 #define REDIRECT(func) \
3608 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3609 REDIRECT(glCopyColorTable);
3610 #undef REDIRECT
3612 if (!init_gl_info())
3613 goto failed;
3615 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3616 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3618 load_extensions();
3619 if (!init_pixel_formats())
3620 goto failed;
3622 return TRUE;
3624 failed:
3625 wine_dlclose(opengl_handle, NULL, 0);
3626 opengl_handle = NULL;
3627 return FALSE;
3631 /***********************************************************************
3632 * sync_gl_view
3634 * Synchronize the Mac GL view position with the Windows child window
3635 * position.
3637 void sync_gl_view(struct macdrv_win_data *data)
3639 RECT rect;
3641 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3643 if (!data->gl_view) return;
3645 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3647 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3648 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3649 data->gl_rect = rect;
3654 /**********************************************************************
3655 * macdrv_wglDescribePixelFormat
3657 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3659 const pixel_format *pf;
3660 const struct color_mode *mode;
3662 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3664 if (!descr) return nb_displayable_formats;
3665 if (size < sizeof(*descr)) return 0;
3667 if (!(pf = get_pixel_format(fmt, FALSE)))
3668 return 0;
3670 memset(descr, 0, sizeof(*descr));
3671 descr->nSize = sizeof(*descr);
3672 descr->nVersion = 1;
3674 descr->dwFlags = PFD_SUPPORT_OPENGL;
3675 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3676 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3677 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3678 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3679 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3681 descr->iPixelType = PFD_TYPE_RGBA;
3683 mode = &color_modes[pf->color_mode];
3684 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3685 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3686 R8G8B8A0 pixel format). If an app depends on that and expects that
3687 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3688 if (mode->alpha_bits)
3689 descr->cColorBits = mode->color_bits;
3690 else
3691 descr->cColorBits = mode->bits_per_pixel;
3692 descr->cRedBits = mode->red_bits;
3693 descr->cRedShift = mode->red_shift;
3694 descr->cGreenBits = mode->green_bits;
3695 descr->cGreenShift = mode->green_shift;
3696 descr->cBlueBits = mode->blue_bits;
3697 descr->cBlueShift = mode->blue_shift;
3698 descr->cAlphaBits = mode->alpha_bits;
3699 descr->cAlphaShift = mode->alpha_shift;
3701 if (pf->accum_mode)
3703 mode = &color_modes[pf->accum_mode - 1];
3704 descr->cAccumBits = mode->color_bits;
3705 descr->cAccumRedBits = mode->red_bits;
3706 descr->cAccumGreenBits = mode->green_bits;
3707 descr->cAccumBlueBits = mode->blue_bits;
3708 descr->cAccumAlphaBits = mode->alpha_bits;
3711 descr->cDepthBits = pf->depth_bits;
3712 descr->cStencilBits = pf->stencil_bits;
3713 descr->cAuxBuffers = pf->aux_buffers;
3714 descr->iLayerType = PFD_MAIN_PLANE;
3716 TRACE("%s\n", debugstr_pf(pf));
3717 return nb_displayable_formats;
3720 /***********************************************************************
3721 * macdrv_wglCopyContext
3723 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3725 CGLError err;
3727 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3729 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3730 if (err != kCGLNoError)
3731 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3732 return (err == kCGLNoError);
3735 /***********************************************************************
3736 * macdrv_wglCreateContext
3738 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3740 struct wgl_context *context;
3742 TRACE("hdc %p\n", hdc);
3744 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
3746 return context;
3749 /***********************************************************************
3750 * macdrv_wglDeleteContext
3752 static void macdrv_wglDeleteContext(struct wgl_context *context)
3754 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3756 EnterCriticalSection(&context_section);
3757 list_remove(&context->entry);
3758 LeaveCriticalSection(&context_section);
3760 macdrv_dispose_opengl_context(context->context);
3761 HeapFree(GetProcessHeap(), 0, context);
3764 /***********************************************************************
3765 * macdrv_wglGetPixelFormat
3767 static int macdrv_wglGetPixelFormat(HDC hdc)
3769 int format;
3771 format = get_dc_pixel_format(hdc);
3773 if (!is_valid_pixel_format(format)) /* not set yet */
3774 format = 0;
3775 else if (!is_displayable_pixel_format(format))
3777 /* Non-displayable formats can't be used with traditional WGL calls.
3778 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3779 format = 1;
3782 TRACE(" hdc %p -> %d\n", hdc, format);
3783 return format;
3786 /***********************************************************************
3787 * macdrv_wglGetProcAddress
3789 static PROC macdrv_wglGetProcAddress(const char *proc)
3791 void *ret;
3793 if (!strncmp(proc, "wgl", 3)) return NULL;
3794 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3795 if (ret)
3797 if (TRACE_ON(wgl))
3799 Dl_info info;
3800 if (dladdr(ret, &info))
3801 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3802 else
3803 TRACE("%s -> %p (no library info)\n", proc, ret);
3806 else
3807 WARN("failed to find proc %s\n", debugstr_a(proc));
3808 return ret;
3811 /***********************************************************************
3812 * macdrv_wglMakeCurrent
3814 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3816 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3817 (context ? context->cglcontext : NULL));
3819 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3822 /**********************************************************************
3823 * macdrv_wglSetPixelFormat
3825 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3827 return set_pixel_format(hdc, fmt, FALSE);
3830 /***********************************************************************
3831 * macdrv_wglShareLists
3833 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3835 macdrv_opengl_context saved_context;
3836 CGLContextObj saved_cglcontext;
3838 TRACE("org %p dest %p\n", org, dest);
3840 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3841 * at context creation time but in case of WGL it is done using wglShareLists.
3843 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3844 * and when a program requests sharing we recreate the destination context if it hasn't been made
3845 * current or when it hasn't shared display lists before.
3848 if (dest->has_been_current)
3850 WARN("could not share display lists, the destination context has been current already\n");
3851 return FALSE;
3853 else if (dest->sharing)
3855 WARN("could not share display lists because dest has already shared lists before\n");
3856 return FALSE;
3859 /* Re-create the Mac context and share display lists */
3860 saved_context = dest->context;
3861 saved_cglcontext = dest->cglcontext;
3862 dest->context = NULL;
3863 dest->cglcontext = NULL;
3864 if (!create_context(dest, org->cglcontext, dest->major))
3866 dest->context = saved_context;
3867 dest->cglcontext = saved_cglcontext;
3868 return FALSE;
3871 /* Implicitly disposes of saved_cglcontext. */
3872 macdrv_dispose_opengl_context(saved_context);
3874 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3875 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3877 org->sharing = TRUE;
3878 dest->sharing = TRUE;
3880 return TRUE;
3883 /**********************************************************************
3884 * macdrv_wglSwapBuffers
3886 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3888 struct wgl_context *context = NtCurrentTeb()->glContext;
3889 BOOL match = FALSE;
3890 HWND hwnd;
3892 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3893 (context ? context->cglcontext : NULL));
3895 if (context)
3896 sync_swap_interval(context);
3898 if ((hwnd = WindowFromDC(hdc)))
3900 struct macdrv_win_data *data;
3902 if (!(data = get_win_data(hwnd)))
3904 SetLastError(ERROR_INVALID_HANDLE);
3905 return FALSE;
3908 if (context && context->draw_view == data->gl_view)
3909 match = TRUE;
3911 release_win_data(data);
3913 else
3915 struct wgl_pbuffer *pbuffer;
3917 EnterCriticalSection(&dc_pbuffers_section);
3918 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3919 LeaveCriticalSection(&dc_pbuffers_section);
3921 if (!pbuffer)
3923 SetLastError(ERROR_INVALID_HANDLE);
3924 return FALSE;
3927 if (context && context->draw_pbuffer == pbuffer)
3928 match = TRUE;
3931 if (match)
3932 macdrv_flush_opengl_context(context->context);
3933 else
3935 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
3937 /* If there is a current context, then wglSwapBuffers should do an implicit
3938 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3939 in the other branch, but we have to do it explicitly here. */
3940 if (context)
3941 pglFlush();
3944 return TRUE;
3947 static struct opengl_funcs opengl_funcs =
3950 macdrv_wglCopyContext, /* p_wglCopyContext */
3951 macdrv_wglCreateContext, /* p_wglCreateContext */
3952 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3953 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3954 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3955 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3956 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3957 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3958 macdrv_wglShareLists, /* p_wglShareLists */
3959 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3963 /**********************************************************************
3964 * macdrv_wine_get_wgl_driver
3966 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3968 if (version != WINE_WGL_DRIVER_VERSION)
3970 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3971 return NULL;
3974 if (!init_opengl()) return (void *)-1;
3976 return &opengl_funcs;