include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / opengl32 / wgl.c
blob19d989e44fc90095b20d8063f7c80391665e7fab
1 /* Window-specific OpenGL functions implementation.
3 * Copyright (c) 1999 Lionel Ulmer
4 * Copyright (c) 2005 Raphael Junqueira
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <math.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "ntuser.h"
32 #include "malloc.h"
34 #include "unixlib.h"
35 #include "private.h"
37 #include "wine/glu.h"
38 #include "wine/debug.h"
39 #include "wine/wgl_driver.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
42 WINE_DECLARE_DEBUG_CHANNEL(fps);
44 static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
46 #define WINE_GL_RESERVED_FORMATS_HDC 2
47 #define WINE_GL_RESERVED_FORMATS_PTR 3
48 #define WINE_GL_RESERVED_FORMATS_NUM 4
49 #define WINE_GL_RESERVED_FORMATS_ONSCREEN 5
51 #ifndef _WIN64
53 static char **wow64_strings;
54 static SIZE_T wow64_strings_count;
56 static CRITICAL_SECTION wow64_cs;
57 static CRITICAL_SECTION_DEBUG wow64_cs_debug =
59 0, 0, &wow64_cs,
60 { &wow64_cs_debug.ProcessLocksList, &wow64_cs_debug.ProcessLocksList },
61 0, 0, { (DWORD_PTR)(__FILE__ ": wow64_cs") }
63 static CRITICAL_SECTION wow64_cs = { &wow64_cs_debug, -1, 0, 0, 0, 0 };
65 static void append_wow64_string( char *str )
67 char **tmp;
69 EnterCriticalSection( &wow64_cs );
71 if (!(tmp = realloc( wow64_strings, (wow64_strings_count + 1) * sizeof(*wow64_strings) )))
72 ERR( "Failed to allocate memory for wow64 strings\n" );
73 else
75 wow64_strings = tmp;
76 wow64_strings[wow64_strings_count] = str;
77 wow64_strings_count += 1;
80 LeaveCriticalSection( &wow64_cs );
83 static void cleanup_wow64_strings(void)
85 while (wow64_strings_count--) free( wow64_strings[wow64_strings_count] );
86 free( wow64_strings );
89 #endif
91 /***********************************************************************
92 * wglGetCurrentReadDCARB
94 * Provided by the WGL_ARB_make_current_read extension.
96 HDC WINAPI wglGetCurrentReadDCARB(void)
98 if (!NtCurrentTeb()->glCurrentRC) return 0;
99 return NtCurrentTeb()->glReserved1[1];
102 /***********************************************************************
103 * wglGetCurrentDC (OPENGL32.@)
105 HDC WINAPI wglGetCurrentDC(void)
107 if (!NtCurrentTeb()->glCurrentRC) return 0;
108 return NtCurrentTeb()->glReserved1[0];
111 /***********************************************************************
112 * wglGetCurrentContext (OPENGL32.@)
114 HGLRC WINAPI wglGetCurrentContext(void)
116 return NtCurrentTeb()->glCurrentRC;
119 /***********************************************************************
120 * wglChoosePixelFormat (OPENGL32.@)
122 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
124 PIXELFORMATDESCRIPTOR format, best;
125 int i, count, best_format;
126 int bestDBuffer = -1, bestStereo = -1;
128 TRACE( "%p %p: size %u version %u flags %lu type %u color %u %u,%u,%u,%u "
129 "accum %u depth %u stencil %u aux %u\n",
130 hdc, ppfd, ppfd->nSize, ppfd->nVersion, ppfd->dwFlags, ppfd->iPixelType,
131 ppfd->cColorBits, ppfd->cRedBits, ppfd->cGreenBits, ppfd->cBlueBits, ppfd->cAlphaBits,
132 ppfd->cAccumBits, ppfd->cDepthBits, ppfd->cStencilBits, ppfd->cAuxBuffers );
134 count = wglDescribePixelFormat( hdc, 0, 0, NULL );
135 if (!count) return 0;
137 best_format = 0;
138 best.dwFlags = 0;
139 best.cAlphaBits = -1;
140 best.cColorBits = -1;
141 best.cDepthBits = -1;
142 best.cStencilBits = -1;
143 best.cAuxBuffers = -1;
145 for (i = 1; i <= count; i++)
147 if (!wglDescribePixelFormat( hdc, i, sizeof(format), &format )) continue;
149 if ((ppfd->iPixelType == PFD_TYPE_COLORINDEX) != (format.iPixelType == PFD_TYPE_COLORINDEX))
151 TRACE( "pixel type mismatch for iPixelFormat=%d\n", i );
152 continue;
155 if ((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(format.dwFlags & PFD_DRAW_TO_BITMAP))
157 TRACE( "PFD_DRAW_TO_BITMAP required but not found for iPixelFormat=%d\n", i );
158 continue;
160 if ((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(format.dwFlags & PFD_DRAW_TO_WINDOW))
162 TRACE( "PFD_DRAW_TO_WINDOW required but not found for iPixelFormat=%d\n", i );
163 continue;
166 if ((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(format.dwFlags & PFD_SUPPORT_GDI))
168 TRACE( "PFD_SUPPORT_GDI required but not found for iPixelFormat=%d\n", i );
169 continue;
171 if ((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(format.dwFlags & PFD_SUPPORT_OPENGL))
173 TRACE( "PFD_SUPPORT_OPENGL required but not found for iPixelFormat=%d\n", i );
174 continue;
177 /* The behavior of PDF_STEREO/PFD_STEREO_DONTCARE and PFD_DOUBLEBUFFER / PFD_DOUBLEBUFFER_DONTCARE
178 * is not very clear on MSDN. They specify that ChoosePixelFormat tries to match pixel formats
179 * with the flag (PFD_STEREO / PFD_DOUBLEBUFFERING) set. Otherwise it says that it tries to match
180 * formats without the given flag set.
181 * A test on Windows using a Radeon 9500pro on WinXP (the driver doesn't support Stereo)
182 * has indicated that a format without stereo is returned when stereo is unavailable.
183 * So in case PFD_STEREO is set, formats that support it should have priority above formats
184 * without. In case PFD_STEREO_DONTCARE is set, stereo is ignored.
186 * To summarize the following is most likely the correct behavior:
187 * stereo not set -> prefer non-stereo formats, but also accept stereo formats
188 * stereo set -> prefer stereo formats, but also accept non-stereo formats
189 * stereo don't care -> it doesn't matter whether we get stereo or not
191 * In Wine we will treat non-stereo the same way as don't care because it makes
192 * format selection even more complicated and second drivers with Stereo advertise
193 * each format twice anyway.
196 /* Doublebuffer, see the comments above */
197 if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE))
199 if (((ppfd->dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) &&
200 ((format.dwFlags & PFD_DOUBLEBUFFER) == (ppfd->dwFlags & PFD_DOUBLEBUFFER)))
201 goto found;
203 if (bestDBuffer != -1 && (format.dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) continue;
205 else if (!best_format)
206 goto found;
208 /* Stereo, see the comments above. */
209 if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE))
211 if (((ppfd->dwFlags & PFD_STEREO) != bestStereo) &&
212 ((format.dwFlags & PFD_STEREO) == (ppfd->dwFlags & PFD_STEREO)))
213 goto found;
215 if (bestStereo != -1 && (format.dwFlags & PFD_STEREO) != bestStereo) continue;
217 else if (!best_format)
218 goto found;
220 /* Below we will do a number of checks to select the 'best' pixelformat.
221 * We assume the precedence cColorBits > cAlphaBits > cDepthBits > cStencilBits -> cAuxBuffers.
222 * The code works by trying to match the most important options as close as possible.
223 * When a reasonable format is found, we will try to match more options.
224 * It appears (see the opengl32 test) that Windows opengl drivers ignore options
225 * like cColorBits, cAlphaBits and friends if they are set to 0, so they are considered
226 * as DONTCARE. At least Serious Sam TSE relies on this behavior. */
228 if (ppfd->cColorBits)
230 if (((ppfd->cColorBits > best.cColorBits) && (format.cColorBits > best.cColorBits)) ||
231 ((format.cColorBits >= ppfd->cColorBits) && (format.cColorBits < best.cColorBits)))
232 goto found;
234 if (best.cColorBits != format.cColorBits) /* Do further checks if the format is compatible */
236 TRACE( "color mismatch for iPixelFormat=%d\n", i );
237 continue;
240 if (ppfd->cAlphaBits)
242 if (((ppfd->cAlphaBits > best.cAlphaBits) && (format.cAlphaBits > best.cAlphaBits)) ||
243 ((format.cAlphaBits >= ppfd->cAlphaBits) && (format.cAlphaBits < best.cAlphaBits)))
244 goto found;
246 if (best.cAlphaBits != format.cAlphaBits)
248 TRACE( "alpha mismatch for iPixelFormat=%d\n", i );
249 continue;
252 if (ppfd->cStencilBits)
254 if (((ppfd->cStencilBits > best.cStencilBits) && (format.cStencilBits > best.cStencilBits)) ||
255 ((format.cStencilBits >= ppfd->cStencilBits) && (format.cStencilBits < best.cStencilBits)))
256 goto found;
258 if (best.cStencilBits != format.cStencilBits)
260 TRACE( "stencil mismatch for iPixelFormat=%d\n", i );
261 continue;
264 if (ppfd->cDepthBits && !(ppfd->dwFlags & PFD_DEPTH_DONTCARE))
266 if (((ppfd->cDepthBits > best.cDepthBits) && (format.cDepthBits > best.cDepthBits)) ||
267 ((format.cDepthBits >= ppfd->cDepthBits) && (format.cDepthBits < best.cDepthBits)))
268 goto found;
270 if (best.cDepthBits != format.cDepthBits)
272 TRACE( "depth mismatch for iPixelFormat=%d\n", i );
273 continue;
276 if (ppfd->cAuxBuffers)
278 if (((ppfd->cAuxBuffers > best.cAuxBuffers) && (format.cAuxBuffers > best.cAuxBuffers)) ||
279 ((format.cAuxBuffers >= ppfd->cAuxBuffers) && (format.cAuxBuffers < best.cAuxBuffers)))
280 goto found;
282 if (best.cAuxBuffers != format.cAuxBuffers)
284 TRACE( "aux mismatch for iPixelFormat=%d\n", i );
285 continue;
288 if (ppfd->dwFlags & PFD_DEPTH_DONTCARE)
290 if (format.cDepthBits < best.cDepthBits)
291 goto found;
292 continue;
295 if (!ppfd->cDepthBits && format.cDepthBits > best.cDepthBits)
296 goto found;
298 continue;
300 found:
301 best_format = i;
302 best = format;
303 bestDBuffer = format.dwFlags & PFD_DOUBLEBUFFER;
304 bestStereo = format.dwFlags & PFD_STEREO;
307 TRACE( "returning %u\n", best_format );
308 return best_format;
311 static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats,
312 UINT *num_onscreen_formats )
314 struct get_pixel_formats_params args = { .teb = NtCurrentTeb(), .hdc = hdc };
315 PVOID *glReserved = NtCurrentTeb()->glReserved1;
316 NTSTATUS status;
318 if (glReserved[WINE_GL_RESERVED_FORMATS_HDC] == hdc)
320 *num_formats = PtrToUlong( glReserved[WINE_GL_RESERVED_FORMATS_NUM] );
321 *num_onscreen_formats = PtrToUlong( glReserved[WINE_GL_RESERVED_FORMATS_ONSCREEN] );
322 return glReserved[WINE_GL_RESERVED_FORMATS_PTR];
325 if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
326 /* Clear formats memory since not all drivers deal with all wgl_pixel_format
327 * fields at the moment. */
328 if (!(args.formats = calloc( args.num_formats, sizeof(*args.formats) ))) goto error;
329 args.max_formats = args.num_formats;
330 if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
332 *num_formats = args.num_formats;
333 *num_onscreen_formats = args.num_onscreen_formats;
335 free( glReserved[WINE_GL_RESERVED_FORMATS_PTR] );
336 glReserved[WINE_GL_RESERVED_FORMATS_HDC] = hdc;
337 glReserved[WINE_GL_RESERVED_FORMATS_PTR] = args.formats;
338 glReserved[WINE_GL_RESERVED_FORMATS_NUM] = ULongToPtr( args.num_formats );
339 glReserved[WINE_GL_RESERVED_FORMATS_ONSCREEN] = ULongToPtr( args.num_onscreen_formats );
341 return args.formats;
343 error:
344 *num_formats = *num_onscreen_formats = 0;
345 free( args.formats );
346 return NULL;
349 static BOOL wgl_attrib_uses_layer( int attrib )
351 switch (attrib)
353 case WGL_ACCELERATION_ARB:
354 case WGL_TRANSPARENT_ARB:
355 case WGL_SHARE_DEPTH_ARB:
356 case WGL_SHARE_STENCIL_ARB:
357 case WGL_SHARE_ACCUM_ARB:
358 case WGL_TRANSPARENT_RED_VALUE_ARB:
359 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
360 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
361 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
362 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
363 case WGL_SUPPORT_GDI_ARB:
364 case WGL_SUPPORT_OPENGL_ARB:
365 case WGL_DOUBLE_BUFFER_ARB:
366 case WGL_STEREO_ARB:
367 case WGL_PIXEL_TYPE_ARB:
368 case WGL_COLOR_BITS_ARB:
369 case WGL_RED_BITS_ARB:
370 case WGL_RED_SHIFT_ARB:
371 case WGL_GREEN_BITS_ARB:
372 case WGL_GREEN_SHIFT_ARB:
373 case WGL_BLUE_BITS_ARB:
374 case WGL_BLUE_SHIFT_ARB:
375 case WGL_ALPHA_BITS_ARB:
376 case WGL_ALPHA_SHIFT_ARB:
377 case WGL_ACCUM_BITS_ARB:
378 case WGL_ACCUM_RED_BITS_ARB:
379 case WGL_ACCUM_GREEN_BITS_ARB:
380 case WGL_ACCUM_BLUE_BITS_ARB:
381 case WGL_ACCUM_ALPHA_BITS_ARB:
382 case WGL_DEPTH_BITS_ARB:
383 case WGL_STENCIL_BITS_ARB:
384 case WGL_AUX_BUFFERS_ARB:
385 case WGL_SAMPLE_BUFFERS_ARB:
386 case WGL_SAMPLES_ARB:
387 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB:
388 case WGL_FLOAT_COMPONENTS_NV:
389 return TRUE;
390 default:
391 return FALSE;
395 static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int attrib, int *value )
397 int val = 0;
398 int valid = -1;
400 switch (attrib)
402 case WGL_DRAW_TO_WINDOW_ARB: val = !!(fmt->pfd.dwFlags & PFD_DRAW_TO_WINDOW); break;
403 case WGL_DRAW_TO_BITMAP_ARB: val = !!(fmt->pfd.dwFlags & PFD_DRAW_TO_BITMAP); break;
404 case WGL_ACCELERATION_ARB:
405 if (fmt->pfd.dwFlags & PFD_GENERIC_ACCELERATED)
406 val = WGL_GENERIC_ACCELERATION_ARB;
407 else if (fmt->pfd.dwFlags & PFD_GENERIC_FORMAT)
408 val = WGL_NO_ACCELERATION_ARB;
409 else
410 val = WGL_FULL_ACCELERATION_ARB;
411 break;
412 case WGL_NEED_PALETTE_ARB: val = !!(fmt->pfd.dwFlags & PFD_NEED_PALETTE); break;
413 case WGL_NEED_SYSTEM_PALETTE_ARB: val = !!(fmt->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE); break;
414 case WGL_SWAP_LAYER_BUFFERS_ARB: val = !!(fmt->pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS); break;
415 case WGL_SWAP_METHOD_ARB: val = fmt->swap_method; break;
416 case WGL_NUMBER_OVERLAYS_ARB:
417 case WGL_NUMBER_UNDERLAYS_ARB:
418 /* We don't support any overlays/underlays. */
419 val = 0;
420 break;
421 case WGL_TRANSPARENT_ARB: val = fmt->transparent; break;
422 case WGL_SHARE_DEPTH_ARB:
423 case WGL_SHARE_STENCIL_ARB:
424 case WGL_SHARE_ACCUM_ARB:
425 /* We support only a main plane at the moment which by definition
426 * shares the depth/stencil/accum buffers with itself. */
427 val = GL_TRUE;
428 break;
429 case WGL_SUPPORT_GDI_ARB: val = !!(fmt->pfd.dwFlags & PFD_SUPPORT_GDI); break;
430 case WGL_SUPPORT_OPENGL_ARB: val = !!(fmt->pfd.dwFlags & PFD_SUPPORT_OPENGL); break;
431 case WGL_DOUBLE_BUFFER_ARB: val = !!(fmt->pfd.dwFlags & PFD_DOUBLEBUFFER); break;
432 case WGL_STEREO_ARB: val = !!(fmt->pfd.dwFlags & PFD_STEREO); break;
433 case WGL_PIXEL_TYPE_ARB: val = fmt->pixel_type; break;
434 case WGL_COLOR_BITS_ARB: val = fmt->pfd.cColorBits; break;
435 case WGL_RED_BITS_ARB: val = fmt->pfd.cRedBits; break;
436 case WGL_RED_SHIFT_ARB: val = fmt->pfd.cRedShift; break;
437 case WGL_GREEN_BITS_ARB: val = fmt->pfd.cGreenBits; break;
438 case WGL_GREEN_SHIFT_ARB: val = fmt->pfd.cGreenShift; break;
439 case WGL_BLUE_BITS_ARB: val = fmt->pfd.cBlueBits; break;
440 case WGL_BLUE_SHIFT_ARB: val = fmt->pfd.cBlueShift; break;
441 case WGL_ALPHA_BITS_ARB: val = fmt->pfd.cAlphaBits; break;
442 case WGL_ALPHA_SHIFT_ARB: val = fmt->pfd.cAlphaShift; break;
443 case WGL_ACCUM_BITS_ARB: val = fmt->pfd.cAccumBits; break;
444 case WGL_ACCUM_RED_BITS_ARB: val = fmt->pfd.cAccumRedBits; break;
445 case WGL_ACCUM_GREEN_BITS_ARB: val = fmt->pfd.cAccumGreenBits; break;
446 case WGL_ACCUM_BLUE_BITS_ARB: val = fmt->pfd.cAccumBlueBits; break;
447 case WGL_ACCUM_ALPHA_BITS_ARB: val = fmt->pfd.cAccumAlphaBits; break;
448 case WGL_DEPTH_BITS_ARB: val = fmt->pfd.cDepthBits; break;
449 case WGL_STENCIL_BITS_ARB: val = fmt->pfd.cStencilBits; break;
450 case WGL_AUX_BUFFERS_ARB: val = fmt->pfd.cAuxBuffers; break;
451 case WGL_DRAW_TO_PBUFFER_ARB: val = fmt->draw_to_pbuffer; break;
452 case WGL_MAX_PBUFFER_PIXELS_ARB: val = fmt->max_pbuffer_pixels; break;
453 case WGL_MAX_PBUFFER_WIDTH_ARB: val = fmt->max_pbuffer_width; break;
454 case WGL_MAX_PBUFFER_HEIGHT_ARB: val = fmt->max_pbuffer_height; break;
455 case WGL_TRANSPARENT_RED_VALUE_ARB:
456 val = fmt->transparent_red_value;
457 valid = !!fmt->transparent_red_value_valid;
458 break;
459 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
460 val = fmt->transparent_green_value;
461 valid = !!fmt->transparent_green_value_valid;
462 break;
463 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
464 val = fmt->transparent_blue_value;
465 valid = !!fmt->transparent_blue_value_valid;
466 break;
467 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
468 val = fmt->transparent_alpha_value;
469 valid = !!fmt->transparent_alpha_value_valid;
470 break;
471 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
472 val = fmt->transparent_index_value;
473 valid = !!fmt->transparent_index_value_valid;
474 break;
475 case WGL_SAMPLE_BUFFERS_ARB: val = fmt->sample_buffers; break;
476 case WGL_SAMPLES_ARB: val = fmt->samples; break;
477 case WGL_BIND_TO_TEXTURE_RGB_ARB: val = fmt->bind_to_texture_rgb; break;
478 case WGL_BIND_TO_TEXTURE_RGBA_ARB: val = fmt->bind_to_texture_rgba; break;
479 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV: val = fmt->bind_to_texture_rectangle_rgb; break;
480 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV: val = fmt->bind_to_texture_rectangle_rgba; break;
481 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: val = fmt->framebuffer_srgb_capable; break;
482 case WGL_FLOAT_COMPONENTS_NV: val = fmt->float_components; break;
483 default:
484 FIXME( "unsupported 0x%x WGL attribute\n", attrib );
485 valid = 0;
486 break;
489 /* If we haven't already determined validity, use the default check */
490 if (valid == -1) valid = val != -1;
491 if (valid) *value = val;
493 return valid;
496 enum attrib_match
498 ATTRIB_MATCH_INVALID = -1,
499 ATTRIB_MATCH_IGNORE,
500 ATTRIB_MATCH_EXACT,
501 ATTRIB_MATCH_MINIMUM,
504 static enum attrib_match wgl_attrib_match_criteria( int attrib )
506 switch (attrib)
508 case WGL_DRAW_TO_WINDOW_ARB:
509 case WGL_DRAW_TO_BITMAP_ARB:
510 case WGL_ACCELERATION_ARB:
511 case WGL_NEED_PALETTE_ARB:
512 case WGL_NEED_SYSTEM_PALETTE_ARB:
513 case WGL_SWAP_LAYER_BUFFERS_ARB:
514 case WGL_SWAP_METHOD_ARB:
515 case WGL_SHARE_DEPTH_ARB:
516 case WGL_SHARE_STENCIL_ARB:
517 case WGL_SHARE_ACCUM_ARB:
518 case WGL_SUPPORT_GDI_ARB:
519 case WGL_SUPPORT_OPENGL_ARB:
520 case WGL_DOUBLE_BUFFER_ARB:
521 case WGL_STEREO_ARB:
522 case WGL_PIXEL_TYPE_ARB:
523 case WGL_BIND_TO_TEXTURE_RGB_ARB:
524 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
525 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
526 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
527 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB:
528 case WGL_FLOAT_COMPONENTS_NV:
529 return ATTRIB_MATCH_EXACT;
530 case WGL_NUMBER_OVERLAYS_ARB:
531 case WGL_NUMBER_UNDERLAYS_ARB:
532 case WGL_COLOR_BITS_ARB:
533 case WGL_RED_BITS_ARB:
534 case WGL_GREEN_BITS_ARB:
535 case WGL_BLUE_BITS_ARB:
536 case WGL_ALPHA_BITS_ARB:
537 case WGL_ACCUM_BITS_ARB:
538 case WGL_ACCUM_RED_BITS_ARB:
539 case WGL_ACCUM_GREEN_BITS_ARB:
540 case WGL_ACCUM_BLUE_BITS_ARB:
541 case WGL_ACCUM_ALPHA_BITS_ARB:
542 case WGL_DEPTH_BITS_ARB:
543 case WGL_STENCIL_BITS_ARB:
544 case WGL_AUX_BUFFERS_ARB:
545 case WGL_SAMPLE_BUFFERS_ARB:
546 case WGL_SAMPLES_ARB:
547 return ATTRIB_MATCH_MINIMUM;
548 case WGL_NUMBER_PIXEL_FORMATS_ARB:
549 case WGL_RED_SHIFT_ARB:
550 case WGL_GREEN_SHIFT_ARB:
551 case WGL_BLUE_SHIFT_ARB:
552 case WGL_ALPHA_SHIFT_ARB:
553 case WGL_TRANSPARENT_ARB:
554 case WGL_TRANSPARENT_RED_VALUE_ARB:
555 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
556 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
557 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
558 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
559 return ATTRIB_MATCH_IGNORE;
560 default:
561 return ATTRIB_MATCH_INVALID;
565 static void filter_format_array( const struct wgl_pixel_format **array,
566 UINT num_formats, int attrib, int value )
568 enum attrib_match match = wgl_attrib_match_criteria( attrib );
569 int fmt_value;
570 UINT i;
572 assert(match != ATTRIB_MATCH_INVALID);
574 if (match == ATTRIB_MATCH_IGNORE) return;
576 for (i = 0; i < num_formats; ++i)
578 if (!array[i]) continue;
579 if (!wgl_pixel_format_get_attrib( array[i], attrib, &fmt_value ) ||
580 (match == ATTRIB_MATCH_EXACT && fmt_value != value) ||
581 (match == ATTRIB_MATCH_MINIMUM && fmt_value < value))
583 array[i] = NULL;
588 static int wgl_attrib_sort_priority( int attrib )
590 switch (attrib)
592 case WGL_DRAW_TO_WINDOW_ARB: return 1;
593 case WGL_DRAW_TO_BITMAP_ARB: return 2;
594 case WGL_ACCELERATION_ARB: return 3;
595 case WGL_COLOR_BITS_ARB: return 4;
596 case WGL_ACCUM_BITS_ARB: return 5;
597 case WGL_PIXEL_TYPE_ARB: return 6;
598 case WGL_ALPHA_BITS_ARB: return 7;
599 case WGL_AUX_BUFFERS_ARB: return 8;
600 case WGL_DEPTH_BITS_ARB: return 9;
601 case WGL_STENCIL_BITS_ARB: return 10;
602 case WGL_DOUBLE_BUFFER_ARB: return 11;
603 case WGL_SWAP_METHOD_ARB: return 12;
604 default: return 100;
608 static int compare_attribs( const void *a, const void *b )
610 return wgl_attrib_sort_priority( *(int *)a ) - wgl_attrib_sort_priority( *(int *)b );
613 static int wgl_attrib_value_priority( int value )
615 switch (value)
617 case WGL_SWAP_UNDEFINED_ARB: return 1;
618 case WGL_SWAP_EXCHANGE_ARB: return 2;
619 case WGL_SWAP_COPY_ARB: return 3;
621 case WGL_FULL_ACCELERATION_ARB: return 1;
622 case WGL_GENERIC_ACCELERATION_ARB: return 2;
623 case WGL_NO_ACCELERATION_ARB: return 3;
625 case WGL_TYPE_RGBA_ARB: return 1;
626 case WGL_TYPE_RGBA_FLOAT_ATI: return 2;
627 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: return 3;
628 case WGL_TYPE_COLORINDEX_ARB: return 4;
630 default: return 100;
634 struct compare_formats_ctx
636 int attribs[256];
637 UINT num_attribs;
640 static int compare_formats( void *arg, const void *a, const void *b )
642 const struct wgl_pixel_format *fmt_a = *(void **)a, *fmt_b = *(void **)b;
643 struct compare_formats_ctx *ctx = arg;
644 int attrib, val_a, val_b;
645 UINT i;
647 if (!fmt_a) return 1;
648 if (!fmt_b) return -1;
650 for (i = 0; i < ctx->num_attribs; ++i)
652 attrib = ctx->attribs[2 * i];
653 if (wgl_pixel_format_get_attrib( fmt_a, attrib, &val_a ) &&
654 wgl_pixel_format_get_attrib( fmt_b, attrib, &val_b ) &&
655 val_a != val_b)
657 switch (attrib)
659 case WGL_ACCELERATION_ARB:
660 case WGL_SWAP_METHOD_ARB:
661 case WGL_PIXEL_TYPE_ARB:
662 return wgl_attrib_value_priority( val_a ) -
663 wgl_attrib_value_priority( val_b );
664 case WGL_COLOR_BITS_ARB:
665 /* Prefer 32bpp over other values */
666 if (val_a >= 32 && val_b >= 32) return val_a - val_b;
667 else return val_b - val_a;
668 default:
669 /* Smaller values first */
670 return val_a - val_b;
675 /* Maintain pixel format id order */
676 return fmt_a - fmt_b;
679 static void compare_formats_ctx_set_attrib( struct compare_formats_ctx *ctx,
680 int attrib, int value )
682 UINT i;
684 /* Overwrite attribute if it exists already */
685 for (i = 0; i < ctx->num_attribs; ++i)
686 if (ctx->attribs[2 * i] == attrib) break;
688 assert(i < ARRAY_SIZE(ctx->attribs) / 2);
690 ctx->attribs[2 * i] = attrib;
691 ctx->attribs[2 * i + 1] = value;
692 if (i == ctx->num_attribs) ++ctx->num_attribs;
695 /***********************************************************************
696 * wglChoosePixelFormatARB (OPENGL32.@)
698 BOOL WINAPI wglChoosePixelFormatARB( HDC hdc, const int *attribs_int, const FLOAT *attribs_float,
699 UINT max_formats, int *formats, UINT *num_formats )
701 struct wgl_pixel_format *wgl_formats;
702 UINT i, num_wgl_formats, num_wgl_onscreen_formats;
703 const struct wgl_pixel_format **format_array;
704 struct compare_formats_ctx ctx = { 0 };
706 TRACE( "hdc %p, attribs_int %p, attribs_float %p, max_formats %u, formats %p, num_formats %p\n",
707 hdc, attribs_int, attribs_float, max_formats, formats, num_formats );
709 wgl_formats = get_pixel_formats( hdc, &num_wgl_formats, &num_wgl_onscreen_formats );
711 /* If the driver doesn't yet provide ARB attrib information in
712 * wgl_pixel_format, fall back to an explicit call. */
713 if (num_wgl_formats && !wgl_formats[0].pixel_type)
715 struct wglChoosePixelFormatARB_params args =
717 .teb = NtCurrentTeb(),
718 .hdc = hdc,
719 .piAttribIList = attribs_int,
720 .pfAttribFList = attribs_float,
721 .nMaxFormats = max_formats,
722 .piFormats = formats,
723 .nNumFormats = num_formats
725 NTSTATUS status;
727 if ((status = UNIX_CALL( wglChoosePixelFormatARB, &args )))
728 WARN( "wglChoosePixelFormatARB returned %#lx\n", status );
730 return args.ret;
733 /* Gather, validate and deduplicate all attributes */
734 for (i = 0; attribs_int && attribs_int[i]; i += 2)
736 if (wgl_attrib_match_criteria( attribs_int[i] ) == ATTRIB_MATCH_INVALID) return FALSE;
737 compare_formats_ctx_set_attrib( &ctx, attribs_int[i], attribs_int[i + 1] );
739 for (i = 0; attribs_float && attribs_float[i]; i += 2)
741 if (wgl_attrib_match_criteria( attribs_float[i] ) == ATTRIB_MATCH_INVALID) return FALSE;
742 compare_formats_ctx_set_attrib( &ctx, attribs_float[i], attribs_float[i + 1] );
745 /* Initialize the format_array with (pointers to) all wgl formats */
746 format_array = malloc( num_wgl_formats * sizeof(*format_array) );
747 if (!format_array) return FALSE;
748 for (i = 0; i < num_wgl_formats; ++i) format_array[i] = &wgl_formats[i];
750 /* Remove formats that are not acceptable */
751 for (i = 0; i < ctx.num_attribs; ++i)
752 filter_format_array( format_array, num_wgl_formats, ctx.attribs[2 * i],
753 ctx.attribs[2 * i + 1] );
755 /* Some attributes we always want to sort by (values don't matter for sorting) */
756 compare_formats_ctx_set_attrib( &ctx, WGL_ACCELERATION_ARB, 0 );
757 compare_formats_ctx_set_attrib( &ctx, WGL_COLOR_BITS_ARB, 0 );
758 compare_formats_ctx_set_attrib( &ctx, WGL_ACCUM_BITS_ARB, 0 );
760 /* Arrange attributes in the order which we want to check them */
761 qsort( ctx.attribs, ctx.num_attribs, 2 * sizeof(*ctx.attribs), compare_attribs );
763 /* Sort pixel formats based on the specified attributes */
764 qsort_s( format_array, num_wgl_formats, sizeof(*format_array), compare_formats, &ctx );
766 /* Return the best max_formats format ids */
767 *num_formats = 0;
768 for (i = 0; i < num_wgl_formats && i < max_formats && format_array[i]; ++i)
770 ++*num_formats;
771 formats[i] = format_array[i] - wgl_formats + 1;
774 free( format_array );
775 return TRUE;
778 INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *ppfd )
780 struct wgl_pixel_format *formats;
781 UINT num_formats, num_onscreen_formats;
783 TRACE( "hdc %p, index %d, size %u, ppfd %p\n", hdc, index, index, ppfd );
785 if (!(formats = get_pixel_formats( hdc, &num_formats, &num_onscreen_formats ))) return 0;
786 if (!ppfd) return num_onscreen_formats;
787 if (size < sizeof(*ppfd)) return 0;
788 if (index <= 0 || index > num_onscreen_formats) return 0;
790 *ppfd = formats[index - 1].pfd;
792 return num_onscreen_formats;
795 /***********************************************************************
796 * wglGetPixelFormatAttribivARB (OPENGL32.@)
798 BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int index, int plane, UINT count,
799 const int *attributes, int *values )
801 static const DWORD invalid_data_error = 0xC007000D;
802 struct wgl_pixel_format *formats;
803 UINT i, num_formats, num_onscreen_formats;
805 TRACE( "hdc %p, index %d, plane %d, count %u, attributes %p, values %p\n",
806 hdc, index, plane, count, attributes, values );
808 formats = get_pixel_formats( hdc, &num_formats, &num_onscreen_formats );
810 /* If the driver doesn't yet provide ARB attrib information in
811 * wgl_pixel_format, fall back to an explicit call. */
812 if (num_formats && !formats[0].pixel_type)
814 struct wglGetPixelFormatAttribivARB_params args =
816 .teb = NtCurrentTeb(),
817 .hdc = hdc,
818 .iPixelFormat = index,
819 .iLayerPlane = plane,
820 .nAttributes = count,
821 .piAttributes = attributes,
822 .piValues = values
824 NTSTATUS status;
826 if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args )))
827 WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status );
829 return args.ret;
832 if (!count) return TRUE;
833 if (count == 1 && attributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
835 values[0] = num_formats;
836 return TRUE;
838 if (index <= 0 || index > num_formats)
840 SetLastError( invalid_data_error );
841 return FALSE;
844 for (i = 0; i < count; ++i)
846 int attrib = attributes[i];
848 if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB)
850 values[i] = num_formats;
852 else if ((plane != 0 && wgl_attrib_uses_layer( attrib )) ||
853 !wgl_pixel_format_get_attrib( &formats[index - 1], attrib, &values[i] ))
855 SetLastError( invalid_data_error );
856 return FALSE;
860 return TRUE;
863 /***********************************************************************
864 * wglGetPixelFormatAttribfvARB (OPENGL32.@)
866 BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int index, int plane, UINT count,
867 const int *attributes, FLOAT *values )
869 int *ivalues;
870 BOOL ret;
871 UINT i;
873 TRACE( "hdc %p, index %d, plane %d, count %u, attributes %p, values %p\n",
874 hdc, index, plane, count, attributes, values );
876 if (!(ivalues = malloc( count * sizeof(int) ))) return FALSE;
878 /* For now we can piggy-back on wglGetPixelFormatAttribivARB, since we don't support
879 * any non-integer attributes. */
880 ret = wglGetPixelFormatAttribivARB( hdc, index, plane, count, attributes, ivalues );
881 if (ret)
883 for (i = 0; i < count; i++)
884 values[i] = ivalues[i];
887 free( ivalues );
888 return ret;
891 /***********************************************************************
892 * wglGetPixelFormat (OPENGL32.@)
894 INT WINAPI wglGetPixelFormat(HDC hdc)
896 struct wglGetPixelFormat_params args = { .teb = NtCurrentTeb(), .hdc = hdc };
897 NTSTATUS status;
899 TRACE( "hdc %p\n", hdc );
901 if ((status = UNIX_CALL( wglGetPixelFormat, &args )))
903 WARN( "wglGetPixelFormat returned %#lx\n", status );
904 SetLastError( ERROR_INVALID_PIXEL_FORMAT );
907 return args.ret;
910 /***********************************************************************
911 * wglSwapBuffers (OPENGL32.@)
913 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
915 struct wglSwapBuffers_params args = { .teb = NtCurrentTeb(), .hdc = hdc };
916 NTSTATUS status;
918 if ((status = UNIX_CALL( wglSwapBuffers, &args ))) WARN( "wglSwapBuffers returned %#lx\n", status );
919 else if (TRACE_ON(fps))
921 static long prev_time, start_time;
922 static unsigned long frames, frames_total;
924 DWORD time = GetTickCount();
925 frames++;
926 frames_total++;
927 /* every 1.5 seconds */
928 if (time - prev_time > 1500)
930 TRACE_(fps)("@ approx %.2ffps, total %.2ffps\n",
931 1000.0*frames/(time - prev_time), 1000.0*frames_total/(time - start_time));
932 prev_time = time;
933 frames = 0;
934 if (start_time == 0) start_time = time;
938 return args.ret;
941 /***********************************************************************
942 * wglCreateLayerContext (OPENGL32.@)
944 HGLRC WINAPI wglCreateLayerContext( HDC hdc, int iLayerPlane )
946 TRACE("(%p,%d)\n", hdc, iLayerPlane);
948 if (iLayerPlane == 0) return wglCreateContext( hdc );
950 FIXME("no handler for layer %d\n", iLayerPlane);
951 return NULL;
954 /***********************************************************************
955 * wglDescribeLayerPlane (OPENGL32.@)
957 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
958 int iPixelFormat,
959 int iLayerPlane,
960 UINT nBytes,
961 LPLAYERPLANEDESCRIPTOR plpd) {
962 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
964 return FALSE;
967 /***********************************************************************
968 * wglGetLayerPaletteEntries (OPENGL32.@)
970 int WINAPI wglGetLayerPaletteEntries( HDC hdc, int plane, int start, int count, COLORREF *colors )
972 FIXME( "hdc %p, plane %d, start %d, count %d, colors %p, stub!\n", hdc, plane, start, count, colors );
973 return 0;
976 /***********************************************************************
977 * wglGetProcAddress (OPENGL32.@)
979 PROC WINAPI wglGetProcAddress( LPCSTR name )
981 struct wglGetProcAddress_params args = { .teb = NtCurrentTeb(), .lpszProc = name };
982 const void *proc;
983 NTSTATUS status;
985 if (!name) return NULL;
986 if ((status = UNIX_CALL( wglGetProcAddress, &args )))
987 WARN( "wglGetProcAddress %s returned %#lx\n", debugstr_a(name), status );
988 if (args.ret == (void *)-1) return NULL;
990 proc = extension_procs[(UINT_PTR)args.ret];
991 TRACE( "returning %s -> %p\n", name, proc );
992 return proc;
995 /***********************************************************************
996 * wglRealizeLayerPalette (OPENGL32.@)
998 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
999 int iLayerPlane,
1000 BOOL bRealize) {
1001 FIXME("()\n");
1003 return FALSE;
1006 /***********************************************************************
1007 * wglSetLayerPaletteEntries (OPENGL32.@)
1009 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
1010 int iLayerPlane,
1011 int iStart,
1012 int cEntries,
1013 const COLORREF *pcr) {
1014 FIXME("(): stub!\n");
1016 return 0;
1019 /***********************************************************************
1020 * wglGetDefaultProcAddress (OPENGL32.@)
1022 PROC WINAPI wglGetDefaultProcAddress( LPCSTR name )
1024 FIXME( "%s: stub\n", debugstr_a(name));
1025 return NULL;
1028 /***********************************************************************
1029 * wglSwapLayerBuffers (OPENGL32.@)
1031 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapLayerBuffers(HDC hdc, UINT fuPlanes)
1033 TRACE("(%p, %08x)\n", hdc, fuPlanes);
1035 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
1036 if (!wglSwapBuffers( hdc )) return FALSE;
1037 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
1040 if (fuPlanes) {
1041 WARN("Following layers unhandled: %08x\n", fuPlanes);
1044 return TRUE;
1047 /***********************************************************************
1048 * wglUseFontBitmaps_common
1050 static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD listBase, BOOL unicode )
1052 GLYPHMETRICS gm;
1053 unsigned int glyph, size = 0;
1054 void *bitmap = NULL, *gl_bitmap = NULL;
1055 int org_alignment;
1056 BOOL ret = TRUE;
1058 glGetIntegerv( GL_UNPACK_ALIGNMENT, &org_alignment );
1059 glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
1061 for (glyph = first; glyph < first + count; glyph++) {
1062 unsigned int needed_size, height, width, width_int;
1064 if (unicode)
1065 needed_size = GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
1066 else
1067 needed_size = GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
1069 TRACE("Glyph: %3d / List: %ld size %d\n", glyph, listBase, needed_size);
1070 if (needed_size == GDI_ERROR) {
1071 ret = FALSE;
1072 break;
1075 if (needed_size > size) {
1076 size = needed_size;
1077 free( bitmap );
1078 free( gl_bitmap );
1079 bitmap = calloc( 1, size );
1080 gl_bitmap = calloc( 1, size );
1082 if (needed_size != 0) {
1083 if (unicode)
1084 ret = (GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm,
1085 size, bitmap, &identity) != GDI_ERROR);
1086 else
1087 ret = (GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm,
1088 size, bitmap, &identity) != GDI_ERROR);
1089 if (!ret) break;
1092 if (TRACE_ON(opengl))
1094 unsigned int bitmask;
1095 unsigned char *bitmap_ = bitmap;
1097 TRACE(" - bbox: %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
1098 TRACE(" - origin: (%ld, %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1099 TRACE(" - increment: %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
1100 if (needed_size != 0) {
1101 TRACE(" - bitmap:\n");
1102 for (height = 0; height < gm.gmBlackBoxY; height++) {
1103 TRACE(" ");
1104 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
1105 if (bitmask == 0) {
1106 bitmap_ += 1;
1107 bitmask = 0x80;
1109 if (*bitmap_ & bitmask)
1110 TRACE("*");
1111 else
1112 TRACE(" ");
1114 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
1115 TRACE("\n");
1120 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
1121 * glyph for it to be drawn properly.
1123 if (needed_size != 0) {
1124 width_int = (gm.gmBlackBoxX + 31) / 32;
1125 for (height = 0; height < gm.gmBlackBoxY; height++) {
1126 for (width = 0; width < width_int; width++) {
1127 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
1128 ((int *) bitmap)[height * width_int + width];
1133 glNewList( listBase++, GL_COMPILE );
1134 if (needed_size != 0) {
1135 glBitmap( gm.gmBlackBoxX, gm.gmBlackBoxY, 0 - gm.gmptGlyphOrigin.x,
1136 (int)gm.gmBlackBoxY - gm.gmptGlyphOrigin.y, gm.gmCellIncX, gm.gmCellIncY, gl_bitmap );
1137 } else {
1138 /* This is the case of 'empty' glyphs like the space character */
1139 glBitmap( 0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL );
1141 glEndList();
1144 glPixelStorei( GL_UNPACK_ALIGNMENT, org_alignment );
1145 free( bitmap );
1146 free( gl_bitmap );
1147 return ret;
1150 /***********************************************************************
1151 * wglUseFontBitmapsA (OPENGL32.@)
1153 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
1155 return wglUseFontBitmaps_common( hdc, first, count, listBase, FALSE );
1158 /***********************************************************************
1159 * wglUseFontBitmapsW (OPENGL32.@)
1161 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
1163 return wglUseFontBitmaps_common( hdc, first, count, listBase, TRUE );
1166 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
1168 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
1169 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
1170 vertex[2] = 0.0;
1173 typedef struct _bezier_vector {
1174 GLdouble x;
1175 GLdouble y;
1176 } bezier_vector;
1178 static double bezier_deviation_squared(const bezier_vector *p)
1180 bezier_vector deviation;
1181 bezier_vector vertex;
1182 bezier_vector base;
1183 double base_length;
1184 double dot;
1186 vertex.x = (p[0].x + p[1].x*2 + p[2].x)/4 - p[0].x;
1187 vertex.y = (p[0].y + p[1].y*2 + p[2].y)/4 - p[0].y;
1189 base.x = p[2].x - p[0].x;
1190 base.y = p[2].y - p[0].y;
1192 base_length = sqrt(base.x*base.x + base.y*base.y);
1193 base.x /= base_length;
1194 base.y /= base_length;
1196 dot = base.x*vertex.x + base.y*vertex.y;
1197 dot = min(max(dot, 0.0), base_length);
1198 base.x *= dot;
1199 base.y *= dot;
1201 deviation.x = vertex.x-base.x;
1202 deviation.y = vertex.y-base.y;
1204 return deviation.x*deviation.x + deviation.y*deviation.y;
1207 static int bezier_approximate(const bezier_vector *p, bezier_vector *points, FLOAT deviation)
1209 bezier_vector first_curve[3];
1210 bezier_vector second_curve[3];
1211 bezier_vector vertex;
1212 int total_vertices;
1214 if(bezier_deviation_squared(p) <= deviation*deviation)
1216 if(points)
1217 *points = p[2];
1218 return 1;
1221 vertex.x = (p[0].x + p[1].x*2 + p[2].x)/4;
1222 vertex.y = (p[0].y + p[1].y*2 + p[2].y)/4;
1224 first_curve[0] = p[0];
1225 first_curve[1].x = (p[0].x + p[1].x)/2;
1226 first_curve[1].y = (p[0].y + p[1].y)/2;
1227 first_curve[2] = vertex;
1229 second_curve[0] = vertex;
1230 second_curve[1].x = (p[2].x + p[1].x)/2;
1231 second_curve[1].y = (p[2].y + p[1].y)/2;
1232 second_curve[2] = p[2];
1234 total_vertices = bezier_approximate(first_curve, points, deviation);
1235 if(points)
1236 points += total_vertices;
1237 total_vertices += bezier_approximate(second_curve, points, deviation);
1238 return total_vertices;
1241 /***********************************************************************
1242 * wglUseFontOutlines_common
1244 static BOOL wglUseFontOutlines_common(HDC hdc,
1245 DWORD first,
1246 DWORD count,
1247 DWORD listBase,
1248 FLOAT deviation,
1249 FLOAT extrusion,
1250 int format,
1251 LPGLYPHMETRICSFLOAT lpgmf,
1252 BOOL unicode)
1254 UINT glyph;
1255 GLUtesselator *tess = NULL;
1256 LOGFONTW lf;
1257 HFONT old_font, unscaled_font;
1258 UINT em_size = 1024;
1259 RECT rc;
1261 TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
1262 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
1264 if(deviation <= 0.0)
1265 deviation = 1.0/em_size;
1267 if(format == WGL_FONT_POLYGONS)
1269 tess = gluNewTess();
1270 if(!tess)
1272 ERR("glu32 is required for this function but isn't available\n");
1273 return FALSE;
1275 gluTessCallback( tess, GLU_TESS_VERTEX, (void *)glVertex3dv );
1276 gluTessCallback( tess, GLU_TESS_BEGIN, (void *)glBegin );
1277 gluTessCallback( tess, GLU_TESS_END, glEnd );
1280 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1281 rc.left = rc.right = rc.bottom = 0;
1282 rc.top = em_size;
1283 DPtoLP(hdc, (POINT*)&rc, 2);
1284 lf.lfHeight = -abs(rc.top - rc.bottom);
1285 lf.lfOrientation = lf.lfEscapement = 0;
1286 unscaled_font = CreateFontIndirectW(&lf);
1287 old_font = SelectObject(hdc, unscaled_font);
1289 for (glyph = first; glyph < first + count; glyph++)
1291 DWORD needed;
1292 GLYPHMETRICS gm;
1293 BYTE *buf;
1294 TTPOLYGONHEADER *pph;
1295 TTPOLYCURVE *ppc;
1296 GLdouble *vertices = NULL;
1297 int vertex_total = -1;
1299 if(unicode)
1300 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
1301 else
1302 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
1304 if(needed == GDI_ERROR)
1305 goto error;
1307 buf = malloc( needed );
1309 if(unicode)
1310 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
1311 else
1312 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
1314 TRACE("glyph %d\n", glyph);
1316 if(lpgmf)
1318 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
1319 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
1320 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
1321 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
1322 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
1323 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
1325 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
1326 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
1327 lpgmf++;
1330 glNewList( listBase++, GL_COMPILE );
1331 glFrontFace( GL_CCW );
1332 if(format == WGL_FONT_POLYGONS)
1334 glNormal3d( 0.0, 0.0, 1.0 );
1335 gluTessNormal(tess, 0, 0, 1);
1336 gluTessBeginPolygon(tess, NULL);
1339 while(!vertices)
1341 if (vertex_total != -1) vertices = malloc( vertex_total * 3 * sizeof(GLdouble) );
1342 vertex_total = 0;
1344 pph = (TTPOLYGONHEADER*)buf;
1345 while((BYTE*)pph < buf + needed)
1347 GLdouble previous[3];
1348 fixed_to_double(pph->pfxStart, em_size, previous);
1350 if(vertices)
1351 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
1353 if (format == WGL_FONT_POLYGONS) gluTessBeginContour( tess );
1354 else glBegin( GL_LINE_LOOP );
1356 if(vertices)
1358 fixed_to_double(pph->pfxStart, em_size, vertices);
1359 if (format == WGL_FONT_POLYGONS) gluTessVertex( tess, vertices, vertices );
1360 else glVertex3d( vertices[0], vertices[1], vertices[2] );
1361 vertices += 3;
1363 vertex_total++;
1365 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
1366 while((char*)ppc < (char*)pph + pph->cb)
1368 int i, j;
1369 int num;
1371 switch(ppc->wType) {
1372 case TT_PRIM_LINE:
1373 for(i = 0; i < ppc->cpfx; i++)
1375 if(vertices)
1377 TRACE("\t\tline to %d, %d\n",
1378 ppc->apfx[i].x.value, ppc->apfx[i].y.value);
1379 fixed_to_double(ppc->apfx[i], em_size, vertices);
1380 if (format == WGL_FONT_POLYGONS) gluTessVertex( tess, vertices, vertices );
1381 else glVertex3d( vertices[0], vertices[1], vertices[2] );
1382 vertices += 3;
1384 fixed_to_double(ppc->apfx[i], em_size, previous);
1385 vertex_total++;
1387 break;
1389 case TT_PRIM_QSPLINE:
1390 for(i = 0; i < ppc->cpfx-1; i++)
1392 bezier_vector curve[3];
1393 bezier_vector *points;
1394 GLdouble curve_vertex[3];
1396 if(vertices)
1397 TRACE("\t\tcurve %d,%d %d,%d\n",
1398 ppc->apfx[i].x.value, ppc->apfx[i].y.value,
1399 ppc->apfx[i + 1].x.value, ppc->apfx[i + 1].y.value);
1401 curve[0].x = previous[0];
1402 curve[0].y = previous[1];
1403 fixed_to_double(ppc->apfx[i], em_size, curve_vertex);
1404 curve[1].x = curve_vertex[0];
1405 curve[1].y = curve_vertex[1];
1406 fixed_to_double(ppc->apfx[i + 1], em_size, curve_vertex);
1407 curve[2].x = curve_vertex[0];
1408 curve[2].y = curve_vertex[1];
1409 if(i < ppc->cpfx-2)
1411 curve[2].x = (curve[1].x + curve[2].x)/2;
1412 curve[2].y = (curve[1].y + curve[2].y)/2;
1414 num = bezier_approximate(curve, NULL, deviation);
1415 points = malloc( num * sizeof(bezier_vector) );
1416 num = bezier_approximate(curve, points, deviation);
1417 vertex_total += num;
1418 if(vertices)
1420 for(j=0; j<num; j++)
1422 TRACE("\t\t\tvertex at %f,%f\n", points[j].x, points[j].y);
1423 vertices[0] = points[j].x;
1424 vertices[1] = points[j].y;
1425 vertices[2] = 0.0;
1426 if (format == WGL_FONT_POLYGONS) gluTessVertex( tess, vertices, vertices );
1427 else glVertex3d( vertices[0], vertices[1], vertices[2] );
1428 vertices += 3;
1431 free( points );
1432 previous[0] = curve[2].x;
1433 previous[1] = curve[2].y;
1435 break;
1436 default:
1437 ERR("\t\tcurve type = %d\n", ppc->wType);
1438 if (format == WGL_FONT_POLYGONS) gluTessEndContour( tess );
1439 else glEnd();
1440 goto error_in_list;
1443 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
1444 (ppc->cpfx - 1) * sizeof(POINTFX));
1446 if (format == WGL_FONT_POLYGONS) gluTessEndContour( tess );
1447 else glEnd();
1448 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
1452 error_in_list:
1453 if (format == WGL_FONT_POLYGONS) gluTessEndPolygon( tess );
1454 glTranslated( (GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0 );
1455 glEndList();
1456 free( buf );
1457 free( vertices );
1460 error:
1461 DeleteObject(SelectObject(hdc, old_font));
1462 if(format == WGL_FONT_POLYGONS)
1463 gluDeleteTess(tess);
1464 return TRUE;
1468 /***********************************************************************
1469 * wglUseFontOutlinesA (OPENGL32.@)
1471 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
1472 DWORD first,
1473 DWORD count,
1474 DWORD listBase,
1475 FLOAT deviation,
1476 FLOAT extrusion,
1477 int format,
1478 LPGLYPHMETRICSFLOAT lpgmf)
1480 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
1483 /***********************************************************************
1484 * wglUseFontOutlinesW (OPENGL32.@)
1486 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
1487 DWORD first,
1488 DWORD count,
1489 DWORD listBase,
1490 FLOAT deviation,
1491 FLOAT extrusion,
1492 int format,
1493 LPGLYPHMETRICSFLOAT lpgmf)
1495 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
1498 /***********************************************************************
1499 * glDebugEntry (OPENGL32.@)
1501 GLint WINAPI glDebugEntry( GLint unknown1, GLint unknown2 )
1503 return 0;
1506 const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index )
1508 struct glGetStringi_params args =
1510 .teb = NtCurrentTeb(),
1511 .name = name,
1512 .index = index,
1514 NTSTATUS status;
1515 #ifndef _WIN64
1516 GLubyte *wow64_str = NULL;
1517 #endif
1519 TRACE( "name %d, index %d\n", name, index );
1521 #ifndef _WIN64
1522 if (UNIX_CALL( glGetStringi, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
1523 #endif
1524 if ((status = UNIX_CALL( glGetStringi, &args ))) WARN( "glGetStringi returned %#lx\n", status );
1525 #ifndef _WIN64
1526 if (args.ret != wow64_str) free( wow64_str );
1527 else if (args.ret) append_wow64_string( (char *)args.ret );
1528 #endif
1529 return args.ret;
1532 /***********************************************************************
1533 * glGetString (OPENGL32.@)
1535 const GLubyte * WINAPI glGetString( GLenum name )
1537 struct glGetString_params args = { .teb = NtCurrentTeb(), .name = name };
1538 NTSTATUS status;
1539 #ifndef _WIN64
1540 GLubyte *wow64_str = NULL;
1541 #endif
1543 TRACE( "name %d\n", name );
1545 #ifndef _WIN64
1546 if (UNIX_CALL( glGetString, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
1547 #endif
1548 if ((status = UNIX_CALL( glGetString, &args ))) WARN( "glGetString returned %#lx\n", status );
1549 #ifndef _WIN64
1550 if (args.ret != wow64_str) free( wow64_str );
1551 else if (args.ret) append_wow64_string( (char *)args.ret );
1552 #endif
1553 return args.ret;
1556 const char * WINAPI wglGetExtensionsStringARB( HDC hdc )
1558 struct wglGetExtensionsStringARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc };
1559 NTSTATUS status;
1560 #ifndef _WIN64
1561 char *wow64_str = NULL;
1562 #endif
1564 TRACE( "hdc %p\n", hdc );
1566 #ifndef _WIN64
1567 if (UNIX_CALL( wglGetExtensionsStringARB, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
1568 #endif
1569 if ((status = UNIX_CALL( wglGetExtensionsStringARB, &args ))) WARN( "wglGetExtensionsStringARB returned %#lx\n", status );
1570 #ifndef _WIN64
1571 if (args.ret != wow64_str) free( wow64_str );
1572 else if (args.ret) append_wow64_string( wow64_str );
1573 #endif
1574 return args.ret;
1577 const char * WINAPI wglGetExtensionsStringEXT(void)
1579 struct wglGetExtensionsStringEXT_params args = { .teb = NtCurrentTeb() };
1580 NTSTATUS status;
1581 #ifndef _WIN64
1582 char *wow64_str = NULL;
1583 #endif
1585 TRACE( "\n" );
1587 #ifndef _WIN64
1588 if (UNIX_CALL( wglGetExtensionsStringEXT, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
1589 #endif
1590 if ((status = UNIX_CALL( wglGetExtensionsStringEXT, &args ))) WARN( "wglGetExtensionsStringEXT returned %#lx\n", status );
1591 #ifndef _WIN64
1592 if (args.ret != wow64_str) free( wow64_str );
1593 else if (args.ret) append_wow64_string( wow64_str );
1594 #endif
1595 return args.ret;
1598 const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute )
1600 struct wglQueryCurrentRendererStringWINE_params args = { .teb = NtCurrentTeb(), .attribute = attribute };
1601 NTSTATUS status;
1602 #ifndef _WIN64
1603 char *wow64_str = NULL;
1604 #endif
1606 TRACE( "attribute %d\n", attribute );
1608 #ifndef _WIN64
1609 if (UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
1610 #endif
1611 if ((status = UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ))) WARN( "wglQueryCurrentRendererStringWINE returned %#lx\n", status );
1612 #ifndef _WIN64
1613 if (args.ret != wow64_str) free( wow64_str );
1614 else if (args.ret) append_wow64_string( wow64_str );
1615 #endif
1616 return args.ret;
1619 const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute )
1621 struct wglQueryRendererStringWINE_params args =
1623 .teb = NtCurrentTeb(),
1624 .dc = dc,
1625 .renderer = renderer,
1626 .attribute = attribute,
1628 NTSTATUS status;
1629 #ifndef _WIN64
1630 char *wow64_str = NULL;
1631 #endif
1633 TRACE( "dc %p, renderer %d, attribute %d\n", dc, renderer, attribute );
1635 #ifndef _WIN64
1636 if (UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
1637 #endif
1638 if ((status = UNIX_CALL( wglQueryRendererStringWINE, &args ))) WARN( "wglQueryRendererStringWINE returned %#lx\n", status );
1639 #ifndef _WIN64
1640 if (args.ret != wow64_str) free( wow64_str );
1641 else if (args.ret) append_wow64_string( wow64_str );
1642 #endif
1643 return args.ret;
1646 #ifndef _WIN64
1647 static void *get_buffer_pointer( GLenum target )
1649 void (WINAPI *p_glGetBufferPointerv)( GLenum target, GLenum pname, void **params );
1650 void *ptr;
1651 if (!(p_glGetBufferPointerv = (void *)wglGetProcAddress( "glGetBufferPointerv" ))) return 0;
1652 p_glGetBufferPointerv( target, GL_BUFFER_MAP_POINTER, &ptr );
1653 return ptr;
1656 static void *get_named_buffer_pointer( GLint buffer )
1658 void (WINAPI *p_glGetNamedBufferPointerv)( GLuint buffer, GLenum pname, void **params );
1659 void *ptr;
1660 if (!(p_glGetNamedBufferPointerv = (void *)wglGetProcAddress( "glGetNamedBufferPointerv" ))) return 0;
1661 p_glGetNamedBufferPointerv( buffer, GL_BUFFER_MAP_POINTER, &ptr );
1662 return ptr;
1664 #endif
1666 static void *gl_map_buffer( enum unix_funcs code, GLenum target, GLenum access )
1668 struct glMapBuffer_params args =
1670 .teb = NtCurrentTeb(),
1671 .target = target,
1672 .access = access,
1674 NTSTATUS status;
1676 TRACE( "target %d, access %d\n", target, access );
1678 if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1679 #ifndef _WIN64
1680 if (status == STATUS_INVALID_ADDRESS)
1682 TRACE( "Unable to map wow64 buffer directly, using copy buffer!\n" );
1683 if (!(args.ret = _aligned_malloc( (size_t)args.ret, 16 ))) status = STATUS_NO_MEMORY;
1684 else if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1685 _aligned_free( args.ret );
1687 #endif
1688 WARN( "glMapBuffer returned %#lx\n", status );
1689 return args.ret;
1692 void * WINAPI glMapBuffer( GLenum target, GLenum access )
1694 return gl_map_buffer( unix_glMapBuffer, target, access );
1697 void * WINAPI glMapBufferARB( GLenum target, GLenum access )
1699 return gl_map_buffer( unix_glMapBufferARB, target, access );
1702 void * WINAPI glMapBufferRange( GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access )
1704 struct glMapBufferRange_params args =
1706 .teb = NtCurrentTeb(),
1707 .target = target,
1708 .offset = offset,
1709 .length = length,
1710 .access = access,
1712 NTSTATUS status;
1714 TRACE( "target %d, offset %Id, length %Id, access %d\n", target, offset, length, access );
1716 if (!(status = UNIX_CALL( glMapBufferRange, &args ))) return args.ret;
1717 #ifndef _WIN64
1718 if (status == STATUS_INVALID_ADDRESS)
1720 TRACE( "Unable to map wow64 buffer directly, using copy buffer!\n" );
1721 if (!(args.ret = _aligned_malloc( length, 16 ))) status = STATUS_NO_MEMORY;
1722 else if (!(status = UNIX_CALL( glMapBufferRange, &args ))) return args.ret;
1723 _aligned_free( args.ret );
1725 #endif
1726 WARN( "glMapBufferRange returned %#lx\n", status );
1727 return args.ret;
1730 static void *gl_map_named_buffer( enum unix_funcs code, GLuint buffer, GLenum access )
1732 struct glMapNamedBuffer_params args =
1734 .teb = NtCurrentTeb(),
1735 .buffer = buffer,
1736 .access = access,
1738 NTSTATUS status;
1740 TRACE( "(%d, %d)\n", buffer, access );
1742 if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1743 #ifndef _WIN64
1744 if (status == STATUS_INVALID_ADDRESS)
1746 TRACE( "Unable to map wow64 buffer directly, using copy buffer!\n" );
1747 if (!(args.ret = _aligned_malloc( (size_t)args.ret, 16 ))) status = STATUS_NO_MEMORY;
1748 else if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1749 _aligned_free( args.ret );
1751 #endif
1752 WARN( "glMapNamedBuffer returned %#lx\n", status );
1753 return args.ret;
1756 void * WINAPI glMapNamedBuffer( GLuint buffer, GLenum access )
1758 return gl_map_named_buffer( unix_glMapNamedBuffer, buffer, access );
1761 void * WINAPI glMapNamedBufferEXT( GLuint buffer, GLenum access )
1763 return gl_map_named_buffer( unix_glMapNamedBufferEXT, buffer, access );
1766 static void *gl_map_named_buffer_range( enum unix_funcs code, GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access )
1768 struct glMapNamedBufferRange_params args =
1770 .teb = NtCurrentTeb(),
1771 .buffer = buffer,
1772 .offset = offset,
1773 .length = length,
1774 .access = access,
1776 NTSTATUS status;
1778 TRACE( "buffer %d, offset %Id, length %Id, access %d\n", buffer, offset, length, access );
1780 if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1781 #ifndef _WIN64
1782 if (status == STATUS_INVALID_ADDRESS)
1784 TRACE( "Unable to map wow64 buffer directly, using copy buffer!\n" );
1785 if (!(args.ret = _aligned_malloc( length, 16 ))) status = STATUS_NO_MEMORY;
1786 else if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1787 _aligned_free( args.ret );
1789 #endif
1790 WARN( "glMapNamedBufferRange returned %#lx\n", status );
1791 return args.ret;
1794 void * WINAPI glMapNamedBufferRange( GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access )
1796 return gl_map_named_buffer_range( unix_glMapNamedBufferRange, buffer, offset, length, access );
1799 void * WINAPI glMapNamedBufferRangeEXT( GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access )
1801 return gl_map_named_buffer_range( unix_glMapNamedBufferRangeEXT, buffer, offset, length, access );
1804 static GLboolean gl_unmap_buffer( enum unix_funcs code, GLenum target )
1806 struct glUnmapBuffer_params args =
1808 .teb = NtCurrentTeb(),
1809 .target = target,
1811 NTSTATUS status;
1812 #ifndef _WIN64
1813 void *ptr = get_buffer_pointer( target );
1814 #endif
1816 TRACE( "target %d\n", target );
1818 if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1819 #ifndef _WIN64
1820 if (status == STATUS_INVALID_ADDRESS)
1822 TRACE( "Releasing wow64 copy buffer %p\n", ptr );
1823 _aligned_free( ptr );
1824 return args.ret;
1826 #endif
1827 WARN( "glUnmapBuffer returned %#lx\n", status );
1828 return args.ret;
1831 GLboolean WINAPI glUnmapBuffer( GLenum target )
1833 return gl_unmap_buffer( unix_glUnmapBuffer, target );
1836 GLboolean WINAPI glUnmapBufferARB( GLenum target )
1838 return gl_unmap_buffer( unix_glUnmapBufferARB, target );
1841 static GLboolean gl_unmap_named_buffer( enum unix_funcs code, GLuint buffer )
1843 struct glUnmapNamedBuffer_params args =
1845 .teb = NtCurrentTeb(),
1846 .buffer = buffer,
1848 NTSTATUS status;
1849 #ifndef _WIN64
1850 void *ptr = get_named_buffer_pointer( buffer );
1851 #endif
1853 TRACE( "buffer %d\n", buffer );
1855 if (!(status = WINE_UNIX_CALL( code, &args ))) return args.ret;
1856 #ifndef _WIN64
1857 if (status == STATUS_INVALID_ADDRESS)
1859 TRACE( "Releasing wow64 copy buffer %p\n", ptr );
1860 _aligned_free( ptr );
1861 return args.ret;
1863 #endif
1864 WARN( "glUnmapNamedBuffer returned %#lx\n", status );
1865 return args.ret;
1868 GLboolean WINAPI glUnmapNamedBuffer( GLuint buffer )
1870 return gl_unmap_named_buffer( unix_glUnmapNamedBuffer, buffer );
1873 GLboolean WINAPI glUnmapNamedBufferEXT( GLuint buffer )
1875 return gl_unmap_named_buffer( unix_glUnmapNamedBufferEXT, buffer );
1878 static NTSTATUS WINAPI call_opengl_debug_message_callback( void *args, ULONG size )
1880 struct wine_gl_debug_message_params *params = args;
1881 params->user_callback( params->source, params->type, params->id, params->severity,
1882 params->length, params->message, params->user_data );
1883 return STATUS_SUCCESS;
1886 /***********************************************************************
1887 * OpenGL initialisation routine
1889 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1891 KERNEL_CALLBACK_PROC *kernel_callback_table;
1892 NTSTATUS status;
1894 switch(reason)
1896 case DLL_PROCESS_ATTACH:
1897 if ((status = __wine_init_unix_call()))
1899 ERR( "Failed to load unixlib, status %#lx\n", status );
1900 return FALSE;
1903 kernel_callback_table = NtCurrentTeb()->Peb->KernelCallbackTable;
1904 kernel_callback_table[NtUserCallOpenGLDebugMessageCallback] = call_opengl_debug_message_callback;
1905 /* fallthrough */
1906 case DLL_THREAD_ATTACH:
1907 if ((status = UNIX_CALL( thread_attach, NtCurrentTeb() )))
1909 WARN( "Failed to initialize thread, status %#lx\n", status );
1910 return FALSE;
1912 break;
1914 case DLL_PROCESS_DETACH:
1915 if (reserved) break;
1916 UNIX_CALL( process_detach, NULL );
1917 #ifndef _WIN64
1918 cleanup_wow64_strings();
1919 #endif
1920 /* fallthrough */
1921 case DLL_THREAD_DETACH:
1922 free( NtCurrentTeb()->glReserved1[WINE_GL_RESERVED_FORMATS_PTR] );
1923 return TRUE;
1925 return TRUE;