As an intermediate step on the way to !5388, I wanted to focus on the infrastructure that will allow us to pass pixel format information from the driver to the PE side. This MR introduces the mechanism to perform this information exchange and uses it to implement `wglDescribePixelFormat` on the PE side. In the current RFC state this MR:
1. Introduces `p_get_pixel_format` driver API to allow drivers to provide pixel format information. 2. Implements `wglDescribePixelFormat` on the PE side using the pixel format information. If the driver doesn't implement `p_get_pixel_format` we fall back to the `wglDescribePixelFormat` driver implementation (temporary measure until all drivers are updated). 3. Caches pixel format information in `NtCurrentTeb()->glReserved1[]`. 4. Implements `p_get_pixel_format` API and removes the custom `wglDescribePixelFormat` for winewayland.
At this point would like to get some more feedback about this approach and the technical details. If the direction seems promising, here are the next steps to get to a final MR:
1. Implement `p_get_pixel_format` for winex11, winemac and dibdrv and remove their custom `wglDescribePixelFormat` implementations. 2. Remove the `wglDescribePixelFormat` driver API.
Thanks!
From: Alexandros Frantzis alexandros.frantzis@collabora.com
We want to use wgl_pixel_format in the wgl driver API. --- dlls/winex11.drv/opengl.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 68c8214b835..2482a07212a 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -184,7 +184,7 @@ static char wglExtensions[4096]; static int glxVersion[2]; static int glx_opcode;
-struct wgl_pixel_format +struct glx_pixel_format { GLXFBConfig fbconfig; XVisualInfo *visual; @@ -199,7 +199,7 @@ struct wgl_context BOOL has_been_current; BOOL sharing; BOOL gl3_context; - const struct wgl_pixel_format *fmt; + const struct glx_pixel_format *fmt; int numAttribs; /* This is needed for delaying wglCreateContextAttribsARB */ int attribList[16]; /* This is needed for delaying wglCreateContextAttribsARB */ GLXContext ctx; @@ -226,7 +226,7 @@ struct gl_drawable Window window; /* window if drawable is a GLXWindow */ Colormap colormap; /* colormap for the client window */ Pixmap pixmap; /* base pixmap if drawable is a GLXPixmap */ - const struct wgl_pixel_format *format; /* pixel format for the drawable */ + const struct glx_pixel_format *format; /* pixel format for the drawable */ SIZE pixmap_size; /* pixmap size for GLXPixmap drawables */ int swap_interval; BOOL refresh_swap_interval; @@ -236,7 +236,7 @@ struct gl_drawable struct wgl_pbuffer { struct gl_drawable *gl; - const struct wgl_pixel_format* fmt; + const struct glx_pixel_format* fmt; int width; int height; int* attribList; @@ -268,7 +268,7 @@ static XContext gl_pbuffer_context;
static struct list context_list = LIST_INIT( context_list ); static struct list pbuffer_list = LIST_INIT( pbuffer_list ); -static struct wgl_pixel_format *pixel_formats; +static struct glx_pixel_format *pixel_formats; static int nb_pixel_formats, nb_onscreen_formats; static BOOL use_render_texture_emulation = TRUE;
@@ -1000,7 +1000,7 @@ static BOOL check_fbconfig_bitmap_capability(Display *display, GLXFBConfig fbcon
static void init_pixel_formats( Display *display ) { - struct wgl_pixel_format *list; + struct glx_pixel_format *list; int size = 0, onscreen_size = 0; int fmt_id, nCfgs, i, run, bmp_formats; GLXFBConfig* cfgs; @@ -1119,7 +1119,7 @@ static inline BOOL is_onscreen_pixel_format( int format ) return format > 0 && format <= nb_onscreen_formats; }
-static inline int pixel_format_index( const struct wgl_pixel_format *format ) +static inline int pixel_format_index( const struct glx_pixel_format *format ) { return format - pixel_formats + 1; } @@ -1129,7 +1129,7 @@ static inline int pixel_format_index( const struct wgl_pixel_format *format ) * Wine's main visual and offscreen formats (if they are available). * This function converts a WGL format to its corresponding GLX one. */ -static const struct wgl_pixel_format *get_pixel_format(Display *display, int iPixelFormat, BOOL AllowOffscreen) +static const struct glx_pixel_format *get_pixel_format(Display *display, int iPixelFormat, BOOL AllowOffscreen) { /* Check if the pixelformat is valid. Note that it is legal to pass an invalid * iPixelFormat in case of probing the number of pixelformats. @@ -1308,7 +1308,7 @@ static GLXContext create_glxcontext(Display *display, struct wgl_context *contex /*********************************************************************** * create_gl_drawable */ -static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel_format *format, BOOL known_child, +static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct glx_pixel_format *format, BOOL known_child, BOOL mutable_pf ) { struct gl_drawable *gl, *prev; @@ -1400,7 +1400,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel /*********************************************************************** * set_win_format */ -static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format, BOOL internal ) +static BOOL set_win_format( HWND hwnd, const struct glx_pixel_format *format, BOOL internal ) { struct gl_drawable *old, *gl;
@@ -1431,7 +1431,7 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format, BO
static BOOL set_pixel_format( HDC hdc, int format, BOOL internal ) { - const struct wgl_pixel_format *fmt; + const struct glx_pixel_format *fmt; int value; HWND hwnd = NtUserWindowFromDC( hdc ); int prev; @@ -1562,7 +1562,7 @@ static int describe_pixel_format( int iPixelFormat, PIXELFORMATDESCRIPTOR *ppfd, /*XVisualInfo *vis;*/ int value; int rb,gb,bb,ab; - const struct wgl_pixel_format *fmt; + const struct glx_pixel_format *fmt;
if (!has_opengl()) return 0;
@@ -2165,7 +2165,7 @@ static struct wgl_pbuffer *X11DRV_wglCreatePbufferARB( HDC hdc, int iPixelFormat const int *piAttribList ) { struct wgl_pbuffer* object; - const struct wgl_pixel_format *fmt; + const struct glx_pixel_format *fmt; int attribs[256]; int nAttribs = 0;
@@ -2708,7 +2708,7 @@ static BOOL X11DRV_wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int UINT nAttributes, const int *piAttributes, int *piValues ) { UINT i; - const struct wgl_pixel_format *fmt; + const struct glx_pixel_format *fmt; int hTest; int tmp; int curGLXAttr = 0;
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Introduce a new wgl driver callback function to allow the driver to provide a complete list of all pixel formats and their attributes. If the driver provides the information use it to implement wglDescribePixelFormat. --- dlls/opengl32/make_opengl | 72 +++++++++++++++++++++++++++++- dlls/opengl32/thunks.c | 9 ---- dlls/opengl32/unix_thunks.c | 4 ++ dlls/opengl32/unix_wgl.c | 35 +++++++++++++++ dlls/opengl32/unixlib.h | 11 +++++ dlls/opengl32/wgl.c | 88 +++++++++++++++++++++++++++++++++++++ include/wine/wgl_driver.h | 56 ++++++++++++++++++++++- 7 files changed, 264 insertions(+), 11 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index ec6c7cbe4df..3369e4add11 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -176,6 +176,7 @@ my %manual_win_thunks = "glUnmapBufferARB" => 1, "glUnmapNamedBuffer" => 1, "glUnmapNamedBufferEXT" => 1, + "wglDescribePixelFormat" => 1, "wglGetCurrentReadDCARB" => 1, "wglGetExtensionsStringARB" => 1, "wglGetExtensionsStringEXT" => 1, @@ -880,6 +881,59 @@ printf HEADER "#define WINE_WGL_DRIVER_VERSION %u\n\n", $wgl_version + 1; print HEADER "struct wgl_context;\n"; print HEADER "struct wgl_pbuffer;\n\n";
+print HEADER "struct wgl_pixel_format\n"; +print HEADER "{\n"; +print HEADER " unsigned int id;\n"; +print HEADER " unsigned int draw_to_window:1;\n"; +print HEADER " unsigned int draw_to_bitmap:1;\n"; +print HEADER " unsigned int acceleration:2; /* 0=No, 1=Generic, 2=Full */\n"; +print HEADER " unsigned int need_palette:1;\n"; +print HEADER " unsigned int need_system_palette:1;\n"; +print HEADER " unsigned int swap_layer_buffers:1;\n"; +print HEADER " unsigned int swap_method:2; /* 0=Exchange, 1=Copy, 2=Undefined */\n"; +print HEADER " unsigned int number_overlays:8;\n"; +print HEADER " unsigned int number_underlays:8;\n"; +print HEADER " unsigned int transparent:1;\n"; +print HEADER " unsigned int support_gdi:1;\n"; +print HEADER " unsigned int support_opengl:1;\n"; +print HEADER " unsigned int double_buffer:1;\n"; +print HEADER " unsigned int stereo:1;\n"; +print HEADER " unsigned int pixel_type:2; /* 0=RGBA, 1=ColorIndex, 2=RGBA_UNSIGNED_FLOAT 3=RGBA_FLOAT */\n"; +print HEADER " unsigned int color_bits:11;\n"; +print HEADER " unsigned int red_bits:8;\n"; +print HEADER " unsigned int red_shift:8;\n"; +print HEADER " unsigned int green_bits:8;\n"; +print HEADER " unsigned int green_shift:8;\n"; +print HEADER " unsigned int blue_bits:8;\n"; +print HEADER " unsigned int blue_shift:8;\n"; +print HEADER " unsigned int alpha_bits:8;\n"; +print HEADER " unsigned int alpha_shift:8;\n"; +print HEADER " unsigned int accum_bits:8;\n"; +print HEADER " unsigned int accum_red_bits:8;\n"; +print HEADER " unsigned int accum_green_bits:8;\n"; +print HEADER " unsigned int accum_blue_bits:8;\n"; +print HEADER " unsigned int accum_alpha_bits:8;\n"; +print HEADER " unsigned int depth_bits:8;\n"; +print HEADER " unsigned int stencil_bits:8;\n"; +print HEADER " unsigned int aux_buffers:8;\n"; +print HEADER " unsigned int draw_to_pbuffer:1;\n"; +print HEADER " unsigned int max_pbuffer_pixels;\n"; +print HEADER " unsigned int max_pbuffer_width;\n"; +print HEADER " unsigned int max_pbuffer_height;\n"; +print HEADER " unsigned int transparent_red_value;\n"; +print HEADER " unsigned int transparent_green_value;\n"; +print HEADER " unsigned int transparent_blue_value;\n"; +print HEADER " unsigned int transparent_alpha_value;\n"; +print HEADER " unsigned int transparent_index_value;\n"; +print HEADER " unsigned int sample_buffers:1;\n"; +print HEADER " unsigned int samples:8;\n"; +print HEADER " unsigned int bind_to_texture_rgb:1;\n"; +print HEADER " unsigned int bind_to_texture_rgba:1;\n"; +print HEADER " unsigned int bind_to_texture_rectangle_rgb:1;\n"; +print HEADER " unsigned int bind_to_texture_rectangle_rgba:1;\n"; +print HEADER " unsigned int framebuffer_srgb_capable:1;\n"; +print HEADER "};\n\n"; + print HEADER "struct opengl_funcs\n{\n"; print HEADER " struct\n {\n"; foreach (sort keys %wgl_functions) @@ -889,6 +943,7 @@ foreach (sort keys %wgl_functions) my $func_ret = get_func_ret( $wgl_functions{$_}, 1 ); printf HEADER " %-10s (WINE_GLAPI *p_$_)($decl_args);\n", $func_ret; } +printf HEADER " %-10s (WINE_GLAPI *p_get_pixel_formats)( struct wgl_pixel_format *formats, UINT max_formats, UINT *num_formats, UINT *num_onscreen_formats );\n", "void"; print HEADER " } wgl;\n\n";
print HEADER " struct\n {\n"; @@ -1012,10 +1067,21 @@ foreach (sort keys %ext_functions) print OUT generate_func_params($_, $ext_functions{$_}); }
+print OUT "struct get_pixel_formats_params\n"; +print OUT "{\n"; +print OUT " TEB *teb;\n"; +print OUT " HDC hdc;\n"; +print OUT " struct wgl_pixel_format *formats;\n"; +print OUT " unsigned int max_formats;\n"; +print OUT " unsigned int num_formats;\n"; +print OUT " unsigned int num_onscreen_formats;\n"; +print OUT "};\n\n"; + print OUT "enum unix_funcs\n"; print OUT "{\n"; print OUT " unix_thread_attach,\n"; print OUT " unix_process_detach,\n"; +print OUT " unix_get_pixel_formats,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -1139,6 +1205,7 @@ print OUT "#endif\n\n";
print OUT "extern NTSTATUS thread_attach( void *args );\n"; print OUT "extern NTSTATUS process_detach( void *args );\n"; +print OUT "extern NTSTATUS get_pixel_formats( void *args );\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -1185,6 +1252,7 @@ print OUT "const unixlib_entry_t __wine_unix_call_funcs[] =\n"; print OUT "{\n"; print OUT " &thread_attach,\n"; print OUT " &process_detach,\n"; +print OUT " &get_pixel_formats,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -1206,7 +1274,8 @@ print OUT "\n"; print OUT "#ifdef _WIN64\n\n"; print OUT "typedef ULONG PTR32;\n\n"; print OUT "extern NTSTATUS wow64_thread_attach( void *args );\n"; -print OUT "extern NTSTATUS wow64_process_detach( void *args );\n\n"; +print OUT "extern NTSTATUS wow64_process_detach( void *args );\n"; +print OUT "extern NTSTATUS wow64_get_pixel_formats( void *args );\n\n";
foreach (sort keys %wgl_functions) { @@ -1250,6 +1319,7 @@ print OUT "\nconst unixlib_entry_t __wine_unix_call_wow64_funcs[] =\n"; print OUT "{\n"; print OUT " wow64_thread_attach,\n"; print OUT " wow64_process_detach,\n"; +print OUT " wow64_get_pixel_formats,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; diff --git a/dlls/opengl32/thunks.c b/dlls/opengl32/thunks.c index c20abdf5488..49f32461de5 100644 --- a/dlls/opengl32/thunks.c +++ b/dlls/opengl32/thunks.c @@ -43,15 +43,6 @@ BOOL WINAPI wglDeleteContext( HGLRC oldContext ) return args.ret; }
-int WINAPI wglDescribePixelFormat( HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd ) -{ - struct wglDescribePixelFormat_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .ipfd = ipfd, .cjpfd = cjpfd, .ppfd = ppfd }; - NTSTATUS status; - TRACE( "hdc %p, ipfd %d, cjpfd %u, ppfd %p\n", hdc, ipfd, cjpfd, ppfd ); - if ((status = UNIX_CALL( wglDescribePixelFormat, &args ))) WARN( "wglDescribePixelFormat returned %#lx\n", status ); - return args.ret; -} - BOOL WINAPI wglMakeCurrent( HDC hDc, HGLRC newContext ) { struct wglMakeCurrent_params args = { .teb = NtCurrentTeb(), .hDc = hDc, .newContext = newContext }; diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index a2889e7cd32..abb436bdc05 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -24,6 +24,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(opengl);
extern NTSTATUS thread_attach( void *args ); extern NTSTATUS process_detach( void *args ); +extern NTSTATUS get_pixel_formats( void *args ); extern NTSTATUS wgl_wglCopyContext( void *args ); extern NTSTATUS wgl_wglCreateContext( void *args ); extern NTSTATUS wgl_wglDeleteContext( void *args ); @@ -24206,6 +24207,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { &thread_attach, &process_detach, + &get_pixel_formats, &wgl_wglCopyContext, &wgl_wglCreateContext, &wgl_wglDeleteContext, @@ -27254,6 +27256,7 @@ typedef ULONG PTR32;
extern NTSTATUS wow64_thread_attach( void *args ); extern NTSTATUS wow64_process_detach( void *args ); +extern NTSTATUS wow64_get_pixel_formats( void *args );
static NTSTATUS wow64_wgl_wglCopyContext( void *args ) { @@ -92326,6 +92329,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { wow64_thread_attach, wow64_process_detach, + wow64_get_pixel_formats, wow64_wgl_wglCopyContext, wow64_wgl_wglCreateContext, wow64_wgl_wglDeleteContext, diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index b75a940d1d6..093dab4efb8 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -1157,6 +1157,16 @@ NTSTATUS process_detach( void *args ) return STATUS_SUCCESS; }
+NTSTATUS get_pixel_formats( void *args ) +{ + struct get_pixel_formats_params *params = args; + const struct opengl_funcs *funcs = get_dc_funcs( params->hdc ); + if (!funcs || !funcs->wgl.p_get_pixel_formats) return STATUS_NOT_IMPLEMENTED; + funcs->wgl.p_get_pixel_formats( params->formats, params->max_formats, + ¶ms->num_formats, ¶ms->num_onscreen_formats ); + return STATUS_SUCCESS; +} + #ifdef _WIN64
typedef ULONG PTR32; @@ -2239,4 +2249,29 @@ NTSTATUS wow64_process_detach( void *args ) return STATUS_SUCCESS; }
+NTSTATUS wow64_get_pixel_formats( void *args ) +{ + struct + { + PTR32 teb; + PTR32 hdc; + PTR32 formats; + UINT max_formats; + UINT num_formats; + UINT num_onscreen_formats; + } *params32 = args; + struct get_pixel_formats_params params = + { + .teb = get_teb64(params32->teb), + .hdc = ULongToPtr(params32->hdc), + .formats = ULongToPtr(params32->formats), + .max_formats = params32->max_formats, + }; + NTSTATUS status; + status = get_pixel_formats( ¶ms ); + params32->num_formats = params.num_formats; + params32->num_onscreen_formats = params.num_onscreen_formats; + return status; +} + #endif diff --git a/dlls/opengl32/unixlib.h b/dlls/opengl32/unixlib.h index 96e42a39b17..3e1e6206478 100644 --- a/dlls/opengl32/unixlib.h +++ b/dlls/opengl32/unixlib.h @@ -25331,10 +25331,21 @@ struct wglSwapIntervalEXT_params BOOL ret; };
+struct get_pixel_formats_params +{ + TEB *teb; + HDC hdc; + struct wgl_pixel_format *formats; + unsigned int max_formats; + unsigned int num_formats; + unsigned int num_onscreen_formats; +}; + enum unix_funcs { unix_thread_attach, unix_process_detach, + unix_get_pixel_formats, unix_wglCopyContext, unix_wglCreateContext, unix_wglDeleteContext, diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index c02436f1675..018d2674c12 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -35,6 +35,7 @@
#include "wine/glu.h" #include "wine/debug.h" +#include "wine/wgl_driver.h"
WINE_DEFAULT_DEBUG_CHANNEL(opengl); WINE_DECLARE_DEBUG_CHANNEL(fps); @@ -294,6 +295,93 @@ INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd) return best_format; }
+static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats, + UINT *num_onscreen_formats ) +{ + struct get_pixel_formats_params args = { .teb = NtCurrentTeb(), .hdc = hdc }; + NTSTATUS status; + + if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error; + if (!(args.formats = malloc( sizeof(*args.formats) * args.num_formats ))) goto error; + args.max_formats = args.num_formats; + if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error; + + *num_formats = args.num_formats; + *num_onscreen_formats = args.num_onscreen_formats; + return args.formats; + +error: + *num_formats = *num_onscreen_formats = 0; + free( args.formats ); + return NULL; +} + +INT WINAPI wglDescribePixelFormat( HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd ) +{ + struct wglDescribePixelFormat_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .ipfd = ipfd, .cjpfd = cjpfd, .ppfd = ppfd }; + NTSTATUS status; + struct wgl_pixel_format *formats, *format; + UINT num_formats, num_onscreen_formats; + + TRACE( "hdc %p, ipfd %d, cjpfd %u, ppfd %p\n", hdc, ipfd, cjpfd, ppfd ); + + if ((formats = get_pixel_formats( hdc, &num_formats, &num_onscreen_formats ))) + { + if (!ppfd) return num_onscreen_formats; + if (cjpfd < sizeof(*ppfd)) return 0; + if (ipfd <= 0 || ipfd > num_onscreen_formats) return 0; + format = &formats[ipfd - 1]; + + memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR); + ppfd->nVersion = 1; + + if (format->draw_to_window) ppfd->dwFlags |= PFD_DRAW_TO_WINDOW; + if (format->draw_to_bitmap) ppfd->dwFlags |= PFD_DRAW_TO_BITMAP; + switch (format->acceleration) + { + case 0: ppfd->dwFlags |= PFD_GENERIC_FORMAT; break; + case 1: ppfd->dwFlags |= PFD_GENERIC_ACCELERATED; break; + default: break; + } + if (format->need_palette) ppfd->dwFlags |= PFD_NEED_PALETTE; + if (format->need_system_palette) ppfd->dwFlags |= PFD_NEED_SYSTEM_PALETTE; + if (format->support_gdi) ppfd->dwFlags |= PFD_SUPPORT_GDI; + if (format->support_opengl) ppfd->dwFlags |= PFD_SUPPORT_OPENGL; + if (format->double_buffer) ppfd->dwFlags |= PFD_DOUBLEBUFFER; + if (format->stereo) ppfd->dwFlags |= PFD_STEREO; + + if (format->pixel_type == 1) + ppfd->iPixelType = PFD_TYPE_COLORINDEX; + else + ppfd->iPixelType = PFD_TYPE_RGBA; + + ppfd->cColorBits = format->color_bits; + ppfd->cRedBits = format->red_bits; + ppfd->cRedShift = format->red_shift; + ppfd->cGreenBits = format->green_bits; + ppfd->cGreenShift = format->green_shift; + ppfd->cBlueBits = format->blue_bits; + ppfd->cBlueShift = format->blue_shift; + ppfd->cAlphaBits = format->alpha_bits; + ppfd->cAlphaShift = format->alpha_shift; + ppfd->cAccumBits = format->accum_bits; + ppfd->cAccumRedBits = format->accum_red_bits; + ppfd->cAccumGreenBits = format->accum_green_bits; + ppfd->cAccumBlueBits = format->accum_blue_bits; + ppfd->cAccumAlphaBits = format->accum_alpha_bits; + ppfd->cDepthBits = format->depth_bits; + ppfd->cStencilBits = format->stencil_bits; + ppfd->cAuxBuffers = format->aux_buffers; + + free( formats ); + return num_onscreen_formats; + } + + if ((status = UNIX_CALL( wglDescribePixelFormat, &args ))) WARN( "wglDescribePixelFormat returned %#lx\n", status ); + return args.ret; +} + /*********************************************************************** * wglGetPixelFormat (OPENGL32.@) */ diff --git a/include/wine/wgl_driver.h b/include/wine/wgl_driver.h index 93ebe7d7f46..044197fc49b 100644 --- a/include/wine/wgl_driver.h +++ b/include/wine/wgl_driver.h @@ -7,11 +7,64 @@ #define WINE_GLAPI #endif
-#define WINE_WGL_DRIVER_VERSION 23 +#define WINE_WGL_DRIVER_VERSION 24
struct wgl_context; struct wgl_pbuffer;
+struct wgl_pixel_format +{ + unsigned int id; + unsigned int draw_to_window:1; + unsigned int draw_to_bitmap:1; + unsigned int acceleration:2; /* 0=No, 1=Generic, 2=Full */ + unsigned int need_palette:1; + unsigned int need_system_palette:1; + unsigned int swap_layer_buffers:1; + unsigned int swap_method:2; /* 0=Exchange, 1=Copy, 2=Undefined */ + unsigned int number_overlays:8; + unsigned int number_underlays:8; + unsigned int transparent:1; + unsigned int support_gdi:1; + unsigned int support_opengl:1; + unsigned int double_buffer:1; + unsigned int stereo:1; + unsigned int pixel_type:2; /* 0=RGBA, 1=ColorIndex, 2=RGBA_UNSIGNED_FLOAT 3=RGBA_FLOAT */ + unsigned int color_bits:11; + unsigned int red_bits:8; + unsigned int red_shift:8; + unsigned int green_bits:8; + unsigned int green_shift:8; + unsigned int blue_bits:8; + unsigned int blue_shift:8; + unsigned int alpha_bits:8; + unsigned int alpha_shift:8; + unsigned int accum_bits:8; + unsigned int accum_red_bits:8; + unsigned int accum_green_bits:8; + unsigned int accum_blue_bits:8; + unsigned int accum_alpha_bits:8; + unsigned int depth_bits:8; + unsigned int stencil_bits:8; + unsigned int aux_buffers:8; + unsigned int draw_to_pbuffer:1; + unsigned int max_pbuffer_pixels; + unsigned int max_pbuffer_width; + unsigned int max_pbuffer_height; + unsigned int transparent_red_value; + unsigned int transparent_green_value; + unsigned int transparent_blue_value; + unsigned int transparent_alpha_value; + unsigned int transparent_index_value; + unsigned int sample_buffers:1; + unsigned int samples:8; + unsigned int bind_to_texture_rgb:1; + unsigned int bind_to_texture_rgba:1; + unsigned int bind_to_texture_rectangle_rgb:1; + unsigned int bind_to_texture_rectangle_rgba:1; + unsigned int framebuffer_srgb_capable:1; +}; + struct opengl_funcs { struct @@ -26,6 +79,7 @@ struct opengl_funcs BOOL (WINE_GLAPI *p_wglSetPixelFormat)( HDC hdc, int ipfd, const PIXELFORMATDESCRIPTOR *ppfd ); BOOL (WINE_GLAPI *p_wglShareLists)( struct wgl_context * hrcSrvShare, struct wgl_context * hrcSrvSource ); BOOL (WINE_GLAPI *p_wglSwapBuffers)( HDC hdc ); + void (WINE_GLAPI *p_get_pixel_formats)( struct wgl_pixel_format *formats, UINT max_formats, UINT *num_formats, UINT *num_onscreen_formats ); } wgl;
struct
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Use the glReserved1 area in the Teb to cache the latest pixel format information requested from the driver. --- dlls/opengl32/wgl.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 018d2674c12..2dffb2c8961 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -42,6 +42,11 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
+#define WINE_GL_RESERVED_FORMATS_HDC 2 +#define WINE_GL_RESERVED_FORMATS_PTR 3 +#define WINE_GL_RESERVED_FORMATS_NUM 4 +#define WINE_GL_RESERVED_FORMATS_ONSCREEN 5 + #ifndef _WIN64
static char **wow64_strings; @@ -299,8 +304,16 @@ static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats, UINT *num_onscreen_formats ) { struct get_pixel_formats_params args = { .teb = NtCurrentTeb(), .hdc = hdc }; + PVOID *glReserved = NtCurrentTeb()->glReserved1; NTSTATUS status;
+ if (glReserved[WINE_GL_RESERVED_FORMATS_HDC] == hdc) + { + *num_formats = PtrToUlong( glReserved[WINE_GL_RESERVED_FORMATS_NUM] ); + *num_onscreen_formats = PtrToUlong( glReserved[WINE_GL_RESERVED_FORMATS_ONSCREEN] ); + return glReserved[WINE_GL_RESERVED_FORMATS_PTR]; + } + if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error; if (!(args.formats = malloc( sizeof(*args.formats) * args.num_formats ))) goto error; args.max_formats = args.num_formats; @@ -308,6 +321,13 @@ static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats,
*num_formats = args.num_formats; *num_onscreen_formats = args.num_onscreen_formats; + + free( glReserved[WINE_GL_RESERVED_FORMATS_PTR] ); + glReserved[WINE_GL_RESERVED_FORMATS_HDC] = hdc; + glReserved[WINE_GL_RESERVED_FORMATS_PTR] = args.formats; + glReserved[WINE_GL_RESERVED_FORMATS_NUM] = ULongToPtr( args.num_formats ); + glReserved[WINE_GL_RESERVED_FORMATS_ONSCREEN] = ULongToPtr( args.num_onscreen_formats ); + return args.formats;
error: @@ -374,7 +394,6 @@ INT WINAPI wglDescribePixelFormat( HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDES ppfd->cStencilBits = format->stencil_bits; ppfd->cAuxBuffers = format->aux_buffers;
- free( formats ); return num_onscreen_formats; }
@@ -1415,6 +1434,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) #ifndef _WIN64 cleanup_wow64_strings(); #endif + /* fallthrough */ + case DLL_THREAD_DETACH: + free( NtCurrentTeb()->glReserved1[WINE_GL_RESERVED_FORMATS_PTR] ); return TRUE; } return TRUE;
From: Alexandros Frantzis alexandros.frantzis@collabora.com
--- dlls/winewayland.drv/opengl.c | 160 ++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 64 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index f072b8063a1..bb5c6c10cab 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -48,6 +48,7 @@ static struct opengl_funcs opengl_funcs; static EGLDisplay egl_display; static char wgl_extensions[4096]; static EGLConfig *egl_configs; +static struct wgl_pixel_format *wgl_pixel_formats; static int num_egl_configs;
#define USE_GL_FUNC(name) #name, @@ -546,61 +547,6 @@ static BOOL wayland_wglDeleteContext(struct wgl_context *ctx)
static BOOL has_opengl(void);
-static int wayland_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, - PIXELFORMATDESCRIPTOR *pfd) -{ - EGLint val; - EGLConfig config; - - if (!has_opengl()) return 0; - if (!pfd) return num_egl_configs; - if (size < sizeof(*pfd)) return 0; - if (fmt <= 0 || fmt > num_egl_configs) return 0; - - config = egl_configs[fmt - 1]; - - memset(pfd, 0, sizeof(*pfd)); - pfd->nSize = sizeof(*pfd); - pfd->nVersion = 1; - pfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | - PFD_SUPPORT_COMPOSITION; - pfd->iPixelType = PFD_TYPE_RGBA; - pfd->iLayerType = PFD_MAIN_PLANE; - - /* Although the documentation describes cColorBits as excluding alpha, real - * drivers tend to return the full pixel size, so do the same. */ - p_eglGetConfigAttrib(egl_display, config, EGL_BUFFER_SIZE, &val); - pfd->cColorBits = val; - p_eglGetConfigAttrib(egl_display, config, EGL_RED_SIZE, &val); - pfd->cRedBits = val; - p_eglGetConfigAttrib(egl_display, config, EGL_GREEN_SIZE, &val); - pfd->cGreenBits = val; - p_eglGetConfigAttrib(egl_display, config, EGL_BLUE_SIZE, &val); - pfd->cBlueBits = val; - p_eglGetConfigAttrib(egl_display, config, EGL_ALPHA_SIZE, &val); - pfd->cAlphaBits = val; - p_eglGetConfigAttrib(egl_display, config, EGL_DEPTH_SIZE, &val); - pfd->cDepthBits = val; - p_eglGetConfigAttrib(egl_display, config, EGL_STENCIL_SIZE, &val); - pfd->cStencilBits = val; - - /* Although we don't get information from EGL about the component shifts - * or the native format, the 0xARGB order is the most common. */ - pfd->cBlueShift = 0; - pfd->cGreenShift = pfd->cBlueBits; - pfd->cRedShift = pfd->cGreenBits + pfd->cBlueBits; - if (pfd->cAlphaBits) - pfd->cAlphaShift = pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits; - else - pfd->cAlphaShift = 0; - - TRACE("fmt %u color %u %u/%u/%u/%u depth %u stencil %u\n", - fmt, pfd->cColorBits, pfd->cRedBits, pfd->cGreenBits, pfd->cBlueBits, - pfd->cAlphaBits, pfd->cDepthBits, pfd->cStencilBits); - - return num_egl_configs; -} - static const char *wayland_wglGetExtensionsStringARB(HDC hdc) { TRACE("() returning "%s"\n", wgl_extensions); @@ -762,6 +708,23 @@ static BOOL wayland_wglSwapIntervalEXT(int interval) return ret; }
+static void wayland_get_pixel_formats(struct wgl_pixel_format *formats, + UINT max_formats, UINT *num_formats, + UINT *num_onscreen_formats) +{ + if (!has_opengl()) + { + *num_formats = *num_onscreen_formats = 0; + return; + } + if (formats) + { + memcpy(formats, wgl_pixel_formats, + sizeof(*formats) * min(max_formats, num_egl_configs)); + } + *num_formats = *num_onscreen_formats = num_egl_configs; +} + static BOOL has_extension(const char *list, const char *ext) { size_t len = strlen(ext); @@ -825,6 +788,63 @@ static BOOL init_opengl_funcs(void) return TRUE; }
+static void convert_egl_to_wgl_format(EGLConfig config, int id, + struct wgl_pixel_format *fmt) +{ + EGLint value; + + fmt->id = id; + fmt->draw_to_window = GL_TRUE; + fmt->acceleration = 2; /* Full acceleration */ + fmt->support_opengl = GL_TRUE; + fmt->double_buffer = GL_TRUE; + +#define SET_ATTRIB(wgl_field, attrib) \ + value = 0; \ + p_eglGetConfigAttrib(egl_display, config, attrib, &value); \ + fmt->wgl_field = value; + +#define SET_ATTRIB_VALUE(wgl_field, attrib, val) \ + value = 0; \ + p_eglGetConfigAttrib(egl_display, config, attrib, &value); \ + fmt->wgl_field = val; + + SET_ATTRIB_VALUE(transparent, EGL_TRANSPARENT_TYPE, (value == EGL_TRANSPARENT_RGB)); + SET_ATTRIB_VALUE(pixel_type, EGL_COLOR_COMPONENT_TYPE_EXT, + (value == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) ? 3 : 0); + + SET_ATTRIB(color_bits, EGL_BUFFER_SIZE); + SET_ATTRIB(red_bits, EGL_RED_SIZE); + SET_ATTRIB(green_bits, EGL_GREEN_SIZE); + SET_ATTRIB(blue_bits, EGL_BLUE_SIZE); + SET_ATTRIB(alpha_bits, EGL_ALPHA_SIZE); + /* Although we don't get information from EGL about the component shifts + * or the native format, the 0xARGB order is the most common. */ + fmt->blue_shift = 0; + fmt->green_shift = fmt->blue_bits; + fmt->red_shift = fmt->green_bits + fmt->blue_bits; + if (fmt->alpha_bits) + fmt->alpha_shift = fmt->red_bits + fmt->green_bits + fmt->blue_bits; + else + fmt->alpha_shift = 0; + + SET_ATTRIB(depth_bits, EGL_DEPTH_SIZE); + SET_ATTRIB(stencil_bits, EGL_STENCIL_SIZE); + SET_ATTRIB(transparent_red_value, EGL_TRANSPARENT_RED_VALUE); + SET_ATTRIB(transparent_green_value, EGL_TRANSPARENT_GREEN_VALUE); + SET_ATTRIB(transparent_blue_value, EGL_TRANSPARENT_BLUE_VALUE); + SET_ATTRIB(sample_buffers, EGL_SAMPLE_BUFFERS); + SET_ATTRIB(samples, EGL_SAMPLES); + SET_ATTRIB(bind_to_texture_rgb, EGL_BIND_TO_TEXTURE_RGB); + SET_ATTRIB(bind_to_texture_rgba, EGL_BIND_TO_TEXTURE_RGBA); + /* Rectangle? */ + + /* TODO: Advertise SRGB and support it for surface creation*/ + +#undef SET_ATTRIB +#undef SET_ATTRIB_VALUE +} + static BOOL init_egl_configs(void) { EGLint i; @@ -852,23 +872,35 @@ static BOOL init_egl_configs(void) return FALSE; }
- if (TRACE_ON(waylanddrv)) + if (!(wgl_pixel_formats = calloc(1, num_egl_configs * sizeof(*wgl_pixel_formats)))) { - for (i = 0; i < num_egl_configs; i++) + ERR("Failed to allocate memory for wgl_pixel_formats\n"); + free(egl_configs); + egl_configs = NULL; + return FALSE; + } + + for (i = 0; i < num_egl_configs; i++) + { + convert_egl_to_wgl_format(egl_configs[i], i + 1, &wgl_pixel_formats[i]); + + if (TRACE_ON(waylanddrv)) { EGLint id, type, visual_id, native, render, color, r, g, b, a, d, s; + p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_NATIVE_VISUAL_ID, &visual_id); p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SURFACE_TYPE, &type); p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_RENDERABLE_TYPE, &render); p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_CONFIG_ID, &id); p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_NATIVE_RENDERABLE, &native); p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_COLOR_BUFFER_TYPE, &color); - p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_RED_SIZE, &r); - p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_GREEN_SIZE, &g); - p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_BLUE_SIZE, &b); - p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_ALPHA_SIZE, &a); - p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_DEPTH_SIZE, &d); - p_eglGetConfigAttrib(egl_display, egl_configs[i], EGL_STENCIL_SIZE, &s); + r = wgl_pixel_formats[i].red_bits; + g = wgl_pixel_formats[i].green_bits; + b = wgl_pixel_formats[i].blue_bits; + a = wgl_pixel_formats[i].alpha_bits; + d = wgl_pixel_formats[i].depth_bits; + s = wgl_pixel_formats[i].stencil_bits; + TRACE("%u: config %d id %d type %x visual %d native %d render %x " "colortype %d rgba %d,%d,%d,%d depth %u stencil %d\n", num_egl_configs, i, id, type, visual_id, native, render, @@ -980,12 +1012,12 @@ static struct opengl_funcs opengl_funcs = .p_wglCopyContext = wayland_wglCopyContext, .p_wglCreateContext = wayland_wglCreateContext, .p_wglDeleteContext = wayland_wglDeleteContext, - .p_wglDescribePixelFormat = wayland_wglDescribePixelFormat, .p_wglGetProcAddress = wayland_wglGetProcAddress, .p_wglMakeCurrent = wayland_wglMakeCurrent, .p_wglSetPixelFormat = wayland_wglSetPixelFormat, .p_wglShareLists = wayland_wglShareLists, .p_wglSwapBuffers = wayland_wglSwapBuffers, + .p_get_pixel_formats = wayland_get_pixel_formats, } };
What about including a PIXELFORMATDESCRIPTOR member, and adding only the missing fields?
Most of the fields are covered by dwFlags bits with a public definition and documented semantic, then you could include a couple of wine-specific iPixelType values for float formats, and add the fields that are missing next to the pfd in the struct.
This would IMO save one conversion and remove the need for comments for the acceleration / swap / pixel type values.
Also using UINT8/16/32 types rather than bitfields would be better, I don't think we need to save bits here.
```suggestion:-0+0 INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *pfd ) ```
Maybe, to make it a bit more understandable?