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
27 #define WIN32_NO_STATUS
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
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
=
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
)
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" );
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
);
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;
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
);
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
);
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
);
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
);
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
);
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
)))
203 if (bestDBuffer
!= -1 && (format
.dwFlags
& PFD_DOUBLEBUFFER
) != bestDBuffer
) continue;
205 else if (!best_format
)
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
)))
215 if (bestStereo
!= -1 && (format
.dwFlags
& PFD_STEREO
) != bestStereo
) continue;
217 else if (!best_format
)
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
)))
234 if (best
.cColorBits
!= format
.cColorBits
) /* Do further checks if the format is compatible */
236 TRACE( "color mismatch for iPixelFormat=%d\n", i
);
240 if (ppfd
->cAlphaBits
)
242 if (((ppfd
->cAlphaBits
> best
.cAlphaBits
) && (format
.cAlphaBits
> best
.cAlphaBits
)) ||
243 ((format
.cAlphaBits
>= ppfd
->cAlphaBits
) && (format
.cAlphaBits
< best
.cAlphaBits
)))
246 if (best
.cAlphaBits
!= format
.cAlphaBits
)
248 TRACE( "alpha mismatch for iPixelFormat=%d\n", i
);
252 if (ppfd
->cStencilBits
)
254 if (((ppfd
->cStencilBits
> best
.cStencilBits
) && (format
.cStencilBits
> best
.cStencilBits
)) ||
255 ((format
.cStencilBits
>= ppfd
->cStencilBits
) && (format
.cStencilBits
< best
.cStencilBits
)))
258 if (best
.cStencilBits
!= format
.cStencilBits
)
260 TRACE( "stencil mismatch for iPixelFormat=%d\n", i
);
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
)))
270 if (best
.cDepthBits
!= format
.cDepthBits
)
272 TRACE( "depth mismatch for iPixelFormat=%d\n", i
);
276 if (ppfd
->cAuxBuffers
)
278 if (((ppfd
->cAuxBuffers
> best
.cAuxBuffers
) && (format
.cAuxBuffers
> best
.cAuxBuffers
)) ||
279 ((format
.cAuxBuffers
>= ppfd
->cAuxBuffers
) && (format
.cAuxBuffers
< best
.cAuxBuffers
)))
282 if (best
.cAuxBuffers
!= format
.cAuxBuffers
)
284 TRACE( "aux mismatch for iPixelFormat=%d\n", i
);
288 if (ppfd
->dwFlags
& PFD_DEPTH_DONTCARE
)
290 if (format
.cDepthBits
< best
.cDepthBits
)
295 if (!ppfd
->cDepthBits
&& format
.cDepthBits
> best
.cDepthBits
)
303 bestDBuffer
= format
.dwFlags
& PFD_DOUBLEBUFFER
;
304 bestStereo
= format
.dwFlags
& PFD_STEREO
;
307 TRACE( "returning %u\n", 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
;
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
);
344 *num_formats
= *num_onscreen_formats
= 0;
345 free( args
.formats
);
349 static BOOL
wgl_attrib_uses_layer( int 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
:
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
:
395 static BOOL
wgl_pixel_format_get_attrib( const struct wgl_pixel_format
*fmt
, int attrib
, int *value
)
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
;
410 val
= WGL_FULL_ACCELERATION_ARB
;
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. */
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. */
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
;
459 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
460 val
= fmt
->transparent_green_value
;
461 valid
= !!fmt
->transparent_green_value_valid
;
463 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
464 val
= fmt
->transparent_blue_value
;
465 valid
= !!fmt
->transparent_blue_value_valid
;
467 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
468 val
= fmt
->transparent_alpha_value
;
469 valid
= !!fmt
->transparent_alpha_value_valid
;
471 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
472 val
= fmt
->transparent_index_value
;
473 valid
= !!fmt
->transparent_index_value_valid
;
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;
484 FIXME( "unsupported 0x%x WGL attribute\n", attrib
);
489 /* If we haven't already determined validity, use the default check */
490 if (valid
== -1) valid
= val
!= -1;
491 if (valid
) *value
= val
;
498 ATTRIB_MATCH_INVALID
= -1,
501 ATTRIB_MATCH_MINIMUM
,
504 static enum attrib_match
wgl_attrib_match_criteria( int 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
:
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
;
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
);
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
))
588 static int wgl_attrib_sort_priority( int 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;
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
)
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;
634 struct compare_formats_ctx
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
;
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
) &&
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
;
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
)
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(),
719 .piAttribIList
= attribs_int
,
720 .pfAttribFList
= attribs_float
,
721 .nMaxFormats
= max_formats
,
722 .piFormats
= formats
,
723 .nNumFormats
= num_formats
727 if ((status
= UNIX_CALL( wglChoosePixelFormatARB
, &args
)))
728 WARN( "wglChoosePixelFormatARB returned %#lx\n", status
);
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 */
768 for (i
= 0; i
< num_wgl_formats
&& i
< max_formats
&& format_array
[i
]; ++i
)
771 formats
[i
] = format_array
[i
] - wgl_formats
+ 1;
774 free( format_array
);
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(),
818 .iPixelFormat
= index
,
819 .iLayerPlane
= plane
,
820 .nAttributes
= count
,
821 .piAttributes
= attributes
,
826 if ((status
= UNIX_CALL( wglGetPixelFormatAttribivARB
, &args
)))
827 WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status
);
832 if (!count
) return TRUE
;
833 if (count
== 1 && attributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
835 values
[0] = num_formats
;
838 if (index
<= 0 || index
> num_formats
)
840 SetLastError( invalid_data_error
);
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
);
863 /***********************************************************************
864 * wglGetPixelFormatAttribfvARB (OPENGL32.@)
866 BOOL WINAPI
wglGetPixelFormatAttribfvARB( HDC hdc
, int index
, int plane
, UINT count
,
867 const int *attributes
, FLOAT
*values
)
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
);
883 for (i
= 0; i
< count
; i
++)
884 values
[i
] = ivalues
[i
];
891 /***********************************************************************
892 * wglGetPixelFormat (OPENGL32.@)
894 INT WINAPI
wglGetPixelFormat(HDC hdc
)
896 struct wglGetPixelFormat_params args
= { .teb
= NtCurrentTeb(), .hdc
= hdc
};
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
);
910 /***********************************************************************
911 * wglSwapBuffers (OPENGL32.@)
913 BOOL WINAPI DECLSPEC_HOTPATCH
wglSwapBuffers( HDC hdc
)
915 struct wglSwapBuffers_params args
= { .teb
= NtCurrentTeb(), .hdc
= hdc
};
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();
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
));
934 if (start_time
== 0) start_time
= time
;
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
);
954 /***********************************************************************
955 * wglDescribeLayerPlane (OPENGL32.@)
957 BOOL WINAPI
wglDescribeLayerPlane(HDC hdc
,
961 LPLAYERPLANEDESCRIPTOR plpd
) {
962 FIXME("(%p,%d,%d,%d,%p)\n", hdc
, iPixelFormat
, iLayerPlane
, nBytes
, plpd
);
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
);
976 /***********************************************************************
977 * wglGetProcAddress (OPENGL32.@)
979 PROC WINAPI
wglGetProcAddress( LPCSTR name
)
981 struct wglGetProcAddress_params args
= { .teb
= NtCurrentTeb(), .lpszProc
= name
};
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
);
995 /***********************************************************************
996 * wglRealizeLayerPalette (OPENGL32.@)
998 BOOL WINAPI
wglRealizeLayerPalette(HDC hdc
,
1006 /***********************************************************************
1007 * wglSetLayerPaletteEntries (OPENGL32.@)
1009 int WINAPI
wglSetLayerPaletteEntries(HDC hdc
,
1013 const COLORREF
*pcr
) {
1014 FIXME("(): stub!\n");
1019 /***********************************************************************
1020 * wglGetDefaultProcAddress (OPENGL32.@)
1022 PROC WINAPI
wglGetDefaultProcAddress( LPCSTR name
)
1024 FIXME( "%s: stub\n", debugstr_a(name
));
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
;
1041 WARN("Following layers unhandled: %08x\n", fuPlanes
);
1047 /***********************************************************************
1048 * wglUseFontBitmaps_common
1050 static BOOL
wglUseFontBitmaps_common( HDC hdc
, DWORD first
, DWORD count
, DWORD listBase
, BOOL unicode
)
1053 unsigned int glyph
, size
= 0;
1054 void *bitmap
= NULL
, *gl_bitmap
= NULL
;
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
;
1065 needed_size
= GetGlyphOutlineW(hdc
, glyph
, GGO_BITMAP
, &gm
, 0, NULL
, &identity
);
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
) {
1075 if (needed_size
> size
) {
1079 bitmap
= calloc( 1, size
);
1080 gl_bitmap
= calloc( 1, size
);
1082 if (needed_size
!= 0) {
1084 ret
= (GetGlyphOutlineW(hdc
, glyph
, GGO_BITMAP
, &gm
,
1085 size
, bitmap
, &identity
) != GDI_ERROR
);
1087 ret
= (GetGlyphOutlineA(hdc
, glyph
, GGO_BITMAP
, &gm
,
1088 size
, bitmap
, &identity
) != GDI_ERROR
);
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
++) {
1104 for (width
= 0, bitmask
= 0x80; width
< gm
.gmBlackBoxX
; width
++, bitmask
>>= 1) {
1109 if (*bitmap_
& bitmask
)
1114 bitmap_
+= (4 - ((UINT_PTR
)bitmap_
& 0x03));
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
);
1138 /* This is the case of 'empty' glyphs like the space character */
1139 glBitmap( 0, 0, 0, 0, gm
.gmCellIncX
, gm
.gmCellIncY
, NULL
);
1144 glPixelStorei( GL_UNPACK_ALIGNMENT
, org_alignment
);
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
;
1173 typedef struct _bezier_vector
{
1178 static double bezier_deviation_squared(const bezier_vector
*p
)
1180 bezier_vector deviation
;
1181 bezier_vector vertex
;
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
);
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
;
1214 if(bezier_deviation_squared(p
) <= deviation
*deviation
)
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
);
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
,
1251 LPGLYPHMETRICSFLOAT lpgmf
,
1255 GLUtesselator
*tess
= NULL
;
1257 HFONT old_font
, unscaled_font
;
1258 UINT em_size
= 1024;
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();
1272 ERR("glu32 is required for this function but isn't available\n");
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;
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
++)
1294 TTPOLYGONHEADER
*pph
;
1296 GLdouble
*vertices
= NULL
;
1297 int vertex_total
= -1;
1300 needed
= GetGlyphOutlineW(hdc
, glyph
, GGO_NATIVE
, &gm
, 0, NULL
, &identity
);
1302 needed
= GetGlyphOutlineA(hdc
, glyph
, GGO_NATIVE
, &gm
, 0, NULL
, &identity
);
1304 if(needed
== GDI_ERROR
)
1307 buf
= malloc( needed
);
1310 GetGlyphOutlineW(hdc
, glyph
, GGO_NATIVE
, &gm
, needed
, buf
, &identity
);
1312 GetGlyphOutlineA(hdc
, glyph
, GGO_NATIVE
, &gm
, needed
, buf
, &identity
);
1314 TRACE("glyph %d\n", glyph
);
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
);
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
);
1341 if (vertex_total
!= -1) vertices
= malloc( vertex_total
* 3 * sizeof(GLdouble
) );
1344 pph
= (TTPOLYGONHEADER
*)buf
;
1345 while((BYTE
*)pph
< buf
+ needed
)
1347 GLdouble previous
[3];
1348 fixed_to_double(pph
->pfxStart
, em_size
, previous
);
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
);
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] );
1365 ppc
= (TTPOLYCURVE
*)((char*)pph
+ sizeof(*pph
));
1366 while((char*)ppc
< (char*)pph
+ pph
->cb
)
1371 switch(ppc
->wType
) {
1373 for(i
= 0; i
< ppc
->cpfx
; i
++)
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] );
1384 fixed_to_double(ppc
->apfx
[i
], em_size
, previous
);
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];
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];
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
;
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
;
1426 if (format
== WGL_FONT_POLYGONS
) gluTessVertex( tess
, vertices
, vertices
);
1427 else glVertex3d( vertices
[0], vertices
[1], vertices
[2] );
1432 previous
[0] = curve
[2].x
;
1433 previous
[1] = curve
[2].y
;
1437 ERR("\t\tcurve type = %d\n", ppc
->wType
);
1438 if (format
== WGL_FONT_POLYGONS
) gluTessEndContour( tess
);
1443 ppc
= (TTPOLYCURVE
*)((char*)ppc
+ sizeof(*ppc
) +
1444 (ppc
->cpfx
- 1) * sizeof(POINTFX
));
1446 if (format
== WGL_FONT_POLYGONS
) gluTessEndContour( tess
);
1448 pph
= (TTPOLYGONHEADER
*)((char*)pph
+ pph
->cb
);
1453 if (format
== WGL_FONT_POLYGONS
) gluTessEndPolygon( tess
);
1454 glTranslated( (GLdouble
)gm
.gmCellIncX
/ em_size
, (GLdouble
)gm
.gmCellIncY
/ em_size
, 0.0 );
1461 DeleteObject(SelectObject(hdc
, old_font
));
1462 if(format
== WGL_FONT_POLYGONS
)
1463 gluDeleteTess(tess
);
1468 /***********************************************************************
1469 * wglUseFontOutlinesA (OPENGL32.@)
1471 BOOL WINAPI
wglUseFontOutlinesA(HDC hdc
,
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
,
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
)
1506 const GLubyte
* WINAPI
glGetStringi( GLenum name
, GLuint index
)
1508 struct glGetStringi_params args
=
1510 .teb
= NtCurrentTeb(),
1516 GLubyte
*wow64_str
= NULL
;
1519 TRACE( "name %d, index %d\n", name
, index
);
1522 if (UNIX_CALL( glGetStringi
, &args
) == STATUS_BUFFER_TOO_SMALL
) args
.ret
= wow64_str
= malloc( (size_t)args
.ret
);
1524 if ((status
= UNIX_CALL( glGetStringi
, &args
))) WARN( "glGetStringi returned %#lx\n", status
);
1526 if (args
.ret
!= wow64_str
) free( wow64_str
);
1527 else if (args
.ret
) append_wow64_string( (char *)args
.ret
);
1532 /***********************************************************************
1533 * glGetString (OPENGL32.@)
1535 const GLubyte
* WINAPI
glGetString( GLenum name
)
1537 struct glGetString_params args
= { .teb
= NtCurrentTeb(), .name
= name
};
1540 GLubyte
*wow64_str
= NULL
;
1543 TRACE( "name %d\n", name
);
1546 if (UNIX_CALL( glGetString
, &args
) == STATUS_BUFFER_TOO_SMALL
) args
.ret
= wow64_str
= malloc( (size_t)args
.ret
);
1548 if ((status
= UNIX_CALL( glGetString
, &args
))) WARN( "glGetString returned %#lx\n", status
);
1550 if (args
.ret
!= wow64_str
) free( wow64_str
);
1551 else if (args
.ret
) append_wow64_string( (char *)args
.ret
);
1556 const char * WINAPI
wglGetExtensionsStringARB( HDC hdc
)
1558 struct wglGetExtensionsStringARB_params args
= { .teb
= NtCurrentTeb(), .hdc
= hdc
};
1561 char *wow64_str
= NULL
;
1564 TRACE( "hdc %p\n", hdc
);
1567 if (UNIX_CALL( wglGetExtensionsStringARB
, &args
) == STATUS_BUFFER_TOO_SMALL
) args
.ret
= wow64_str
= malloc( (size_t)args
.ret
);
1569 if ((status
= UNIX_CALL( wglGetExtensionsStringARB
, &args
))) WARN( "wglGetExtensionsStringARB returned %#lx\n", status
);
1571 if (args
.ret
!= wow64_str
) free( wow64_str
);
1572 else if (args
.ret
) append_wow64_string( wow64_str
);
1577 const char * WINAPI
wglGetExtensionsStringEXT(void)
1579 struct wglGetExtensionsStringEXT_params args
= { .teb
= NtCurrentTeb() };
1582 char *wow64_str
= NULL
;
1588 if (UNIX_CALL( wglGetExtensionsStringEXT
, &args
) == STATUS_BUFFER_TOO_SMALL
) args
.ret
= wow64_str
= malloc( (size_t)args
.ret
);
1590 if ((status
= UNIX_CALL( wglGetExtensionsStringEXT
, &args
))) WARN( "wglGetExtensionsStringEXT returned %#lx\n", status
);
1592 if (args
.ret
!= wow64_str
) free( wow64_str
);
1593 else if (args
.ret
) append_wow64_string( wow64_str
);
1598 const GLchar
* WINAPI
wglQueryCurrentRendererStringWINE( GLenum attribute
)
1600 struct wglQueryCurrentRendererStringWINE_params args
= { .teb
= NtCurrentTeb(), .attribute
= attribute
};
1603 char *wow64_str
= NULL
;
1606 TRACE( "attribute %d\n", attribute
);
1609 if (UNIX_CALL( wglQueryCurrentRendererStringWINE
, &args
) == STATUS_BUFFER_TOO_SMALL
) args
.ret
= wow64_str
= malloc( (size_t)args
.ret
);
1611 if ((status
= UNIX_CALL( wglQueryCurrentRendererStringWINE
, &args
))) WARN( "wglQueryCurrentRendererStringWINE returned %#lx\n", status
);
1613 if (args
.ret
!= wow64_str
) free( wow64_str
);
1614 else if (args
.ret
) append_wow64_string( wow64_str
);
1619 const GLchar
* WINAPI
wglQueryRendererStringWINE( HDC dc
, GLint renderer
, GLenum attribute
)
1621 struct wglQueryRendererStringWINE_params args
=
1623 .teb
= NtCurrentTeb(),
1625 .renderer
= renderer
,
1626 .attribute
= attribute
,
1630 char *wow64_str
= NULL
;
1633 TRACE( "dc %p, renderer %d, attribute %d\n", dc
, renderer
, attribute
);
1636 if (UNIX_CALL( wglQueryCurrentRendererStringWINE
, &args
) == STATUS_BUFFER_TOO_SMALL
) args
.ret
= wow64_str
= malloc( (size_t)args
.ret
);
1638 if ((status
= UNIX_CALL( wglQueryRendererStringWINE
, &args
))) WARN( "wglQueryRendererStringWINE returned %#lx\n", status
);
1640 if (args
.ret
!= wow64_str
) free( wow64_str
);
1641 else if (args
.ret
) append_wow64_string( wow64_str
);
1647 static void *get_buffer_pointer( GLenum target
)
1649 void (WINAPI
*p_glGetBufferPointerv
)( GLenum target
, GLenum pname
, void **params
);
1651 if (!(p_glGetBufferPointerv
= (void *)wglGetProcAddress( "glGetBufferPointerv" ))) return 0;
1652 p_glGetBufferPointerv( target
, GL_BUFFER_MAP_POINTER
, &ptr
);
1656 static void *get_named_buffer_pointer( GLint buffer
)
1658 void (WINAPI
*p_glGetNamedBufferPointerv
)( GLuint buffer
, GLenum pname
, void **params
);
1660 if (!(p_glGetNamedBufferPointerv
= (void *)wglGetProcAddress( "glGetNamedBufferPointerv" ))) return 0;
1661 p_glGetNamedBufferPointerv( buffer
, GL_BUFFER_MAP_POINTER
, &ptr
);
1666 static void *gl_map_buffer( enum unix_funcs code
, GLenum target
, GLenum access
)
1668 struct glMapBuffer_params args
=
1670 .teb
= NtCurrentTeb(),
1676 TRACE( "target %d, access %d\n", target
, access
);
1678 if (!(status
= WINE_UNIX_CALL( code
, &args
))) return args
.ret
;
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
);
1688 WARN( "glMapBuffer returned %#lx\n", status
);
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(),
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
;
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
);
1726 WARN( "glMapBufferRange returned %#lx\n", status
);
1730 static void *gl_map_named_buffer( enum unix_funcs code
, GLuint buffer
, GLenum access
)
1732 struct glMapNamedBuffer_params args
=
1734 .teb
= NtCurrentTeb(),
1740 TRACE( "(%d, %d)\n", buffer
, access
);
1742 if (!(status
= WINE_UNIX_CALL( code
, &args
))) return args
.ret
;
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
);
1752 WARN( "glMapNamedBuffer returned %#lx\n", status
);
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(),
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
;
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
);
1790 WARN( "glMapNamedBufferRange returned %#lx\n", status
);
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(),
1813 void *ptr
= get_buffer_pointer( target
);
1816 TRACE( "target %d\n", target
);
1818 if (!(status
= WINE_UNIX_CALL( code
, &args
))) return args
.ret
;
1820 if (status
== STATUS_INVALID_ADDRESS
)
1822 TRACE( "Releasing wow64 copy buffer %p\n", ptr
);
1823 _aligned_free( ptr
);
1827 WARN( "glUnmapBuffer returned %#lx\n", status
);
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(),
1850 void *ptr
= get_named_buffer_pointer( buffer
);
1853 TRACE( "buffer %d\n", buffer
);
1855 if (!(status
= WINE_UNIX_CALL( code
, &args
))) return args
.ret
;
1857 if (status
== STATUS_INVALID_ADDRESS
)
1859 TRACE( "Releasing wow64 copy buffer %p\n", ptr
);
1860 _aligned_free( ptr
);
1864 WARN( "glUnmapNamedBuffer returned %#lx\n", status
);
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
;
1896 case DLL_PROCESS_ATTACH
:
1897 if ((status
= __wine_init_unix_call()))
1899 ERR( "Failed to load unixlib, status %#lx\n", status
);
1903 kernel_callback_table
= NtCurrentTeb()->Peb
->KernelCallbackTable
;
1904 kernel_callback_table
[NtUserCallOpenGLDebugMessageCallback
] = call_opengl_debug_message_callback
;
1906 case DLL_THREAD_ATTACH
:
1907 if ((status
= UNIX_CALL( thread_attach
, NtCurrentTeb() )))
1909 WARN( "Failed to initialize thread, status %#lx\n", status
);
1914 case DLL_PROCESS_DETACH
:
1915 if (reserved
) break;
1916 UNIX_CALL( process_detach
, NULL
);
1918 cleanup_wow64_strings();
1921 case DLL_THREAD_DETACH
:
1922 free( NtCurrentTeb()->glReserved1
[WINE_GL_RESERVED_FORMATS_PTR
] );