This MR adds a default implementation for `wglChoosePixelFormatARB` (in opengl32.dll) which will be used automatically if the driver populates the wgl_pixel_format ARB fields. Thus winex11 automatically uses this, and this MR removes the driver internal implementation.
The second part of this MR adds `WGL_ARB_pixel_format` support for winewayland (we can move this to a separate MR, but I wanted to have another implementation to better assess the behavior).
The `wglChoosePixelFormatARB` behavior is loosely modeled after the the AMD driver as discussed in https://gitlab.winehq.org/wine/wine/-/merge_requests/5388. I tried to keep things simple to begin with, and the results I am getting in various apps/games are sensible, but please try this out so we can refine further.
From: Alexandros Frantzis alexandros.frantzis@collabora.com
The default implementation will be used automatically if the driver populates the wgl_pixel_format ARB fields. --- dlls/opengl32/make_opengl | 1 + dlls/opengl32/thunks.c | 10 +- dlls/opengl32/wgl.c | 243 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 9 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 771793b9049..54873150da3 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -177,6 +177,7 @@ my %manual_win_thunks = "glUnmapBufferARB" => 1, "glUnmapNamedBuffer" => 1, "glUnmapNamedBufferEXT" => 1, + "wglChoosePixelFormatARB" => 1, "wglGetCurrentReadDCARB" => 1, "wglGetExtensionsStringARB" => 1, "wglGetExtensionsStringEXT" => 1, diff --git a/dlls/opengl32/thunks.c b/dlls/opengl32/thunks.c index 3ee1776daef..ccabbbc7519 100644 --- a/dlls/opengl32/thunks.c +++ b/dlls/opengl32/thunks.c @@ -24164,15 +24164,6 @@ static BOOL WINAPI wglBindTexImageARB( HPBUFFERARB hPbuffer, int iBuffer ) return args.ret; }
-static BOOL WINAPI wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats ) -{ - struct wglChoosePixelFormatARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .piAttribIList = piAttribIList, .pfAttribFList = pfAttribFList, .nMaxFormats = nMaxFormats, .piFormats = piFormats, .nNumFormats = nNumFormats }; - NTSTATUS status; - TRACE( "hdc %p, piAttribIList %p, pfAttribFList %p, nMaxFormats %u, piFormats %p, nNumFormats %p\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats ); - if ((status = UNIX_CALL( wglChoosePixelFormatARB, &args ))) WARN( "wglChoosePixelFormatARB returned %#lx\n", status ); - return args.ret; -} - static HGLRC WINAPI wglCreateContextAttribsARB( HDC hDC, HGLRC hShareContext, const int *attribList ) { struct wglCreateContextAttribsARB_params args = { .teb = NtCurrentTeb(), .hDC = hDC, .hShareContext = hShareContext, .attribList = attribList }; @@ -24319,6 +24310,7 @@ extern GLboolean WINAPI glUnmapBuffer( GLenum target ); extern GLboolean WINAPI glUnmapBufferARB( GLenum target ); extern GLboolean WINAPI glUnmapNamedBuffer( GLuint buffer ); extern GLboolean WINAPI glUnmapNamedBufferEXT( GLuint buffer ); +extern BOOL WINAPI wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats ); extern HDC WINAPI wglGetCurrentReadDCARB(void); extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc ); extern const char * WINAPI wglGetExtensionsStringEXT(void); diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 2ae79a56f9e..c4cdf941fc5 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -492,6 +492,249 @@ static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int return valid; }
+enum attrib_match +{ + ATTRIB_MATCH_IGNORE, + ATTRIB_MATCH_EXACT, + ATTRIB_MATCH_MINIMUM, +}; + +static enum attrib_match wgl_attrib_match_criteria( int attrib ) +{ + switch (attrib) + { + case WGL_DRAW_TO_WINDOW_ARB: + case WGL_DRAW_TO_BITMAP_ARB: + case WGL_ACCELERATION_ARB: + case WGL_NEED_PALETTE_ARB: + case WGL_NEED_SYSTEM_PALETTE_ARB: + case WGL_SWAP_LAYER_BUFFERS_ARB: + case WGL_SWAP_METHOD_ARB: + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_ARB: + case WGL_SUPPORT_GDI_ARB: + case WGL_SUPPORT_OPENGL_ARB: + case WGL_DOUBLE_BUFFER_ARB: + case WGL_STEREO_ARB: + case WGL_PIXEL_TYPE_ARB: + case WGL_BIND_TO_TEXTURE_RGB_ARB: + case WGL_BIND_TO_TEXTURE_RGBA_ARB: + case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV: + case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV: + case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: + case WGL_FLOAT_COMPONENTS_NV: + return ATTRIB_MATCH_EXACT; + case WGL_NUMBER_OVERLAYS_ARB: + case WGL_NUMBER_UNDERLAYS_ARB: + case WGL_COLOR_BITS_ARB: + case WGL_RED_BITS_ARB: + case WGL_GREEN_BITS_ARB: + case WGL_BLUE_BITS_ARB: + case WGL_ALPHA_BITS_ARB: + case WGL_ACCUM_BITS_ARB: + case WGL_ACCUM_RED_BITS_ARB: + case WGL_ACCUM_GREEN_BITS_ARB: + case WGL_ACCUM_BLUE_BITS_ARB: + case WGL_ACCUM_ALPHA_BITS_ARB: + case WGL_DEPTH_BITS_ARB: + case WGL_STENCIL_BITS_ARB: + case WGL_AUX_BUFFERS_ARB: + case WGL_SAMPLE_BUFFERS_ARB: + case WGL_SAMPLES_ARB: + return ATTRIB_MATCH_MINIMUM; + default: + return ATTRIB_MATCH_IGNORE; + } +} + +static void filter_format_array( const struct wgl_pixel_format **array, + UINT num_formats, int attrib, int value ) +{ + enum attrib_match match = wgl_attrib_match_criteria( attrib ); + int fmt_value; + UINT i; + + if (match == ATTRIB_MATCH_IGNORE) return; + + for (i = 0; i < num_formats; ++i) + { + if (!array[i]) continue; + if (!wgl_pixel_format_get_attrib( array[i], attrib, &fmt_value ) || + (match == ATTRIB_MATCH_EXACT && fmt_value != value) || + (match == ATTRIB_MATCH_MINIMUM && fmt_value < value)) + { + array[i] = NULL; + } + } +} + +static int wgl_attrib_sort_priority( int attrib ) +{ + switch (attrib) + { + case WGL_DRAW_TO_WINDOW_ARB: return 1; + case WGL_DRAW_TO_BITMAP_ARB: return 2; + case WGL_ACCELERATION_ARB: return 3; + case WGL_COLOR_BITS_ARB: return 4; + case WGL_PIXEL_TYPE_ARB: return 5; + case WGL_ALPHA_BITS_ARB: return 6; + case WGL_AUX_BUFFERS_ARB: return 7; + case WGL_DEPTH_BITS_ARB: return 8; + case WGL_STENCIL_BITS_ARB: return 9; + case WGL_ACCUM_BITS_ARB: return 10; + case WGL_DOUBLE_BUFFER_ARB: return 11; + case WGL_SWAP_METHOD_ARB: return 12; + default: return 100; + } +} + +static int compare_attribs( const void *a, const void *b ) +{ + int prio_a = wgl_attrib_sort_priority( *(int *)a ); + int prio_b = wgl_attrib_sort_priority( *(int *)b ); + + if (prio_a == prio_b) return 0; + else if (prio_a < prio_b) return -1; + else return 1; +} + +static int wgl_attrib_value_priority( int value ) +{ + switch (value) + { + case WGL_SWAP_UNDEFINED_ARB: return 1; + case WGL_SWAP_EXCHANGE_ARB: return 2; + case WGL_SWAP_COPY_ARB: return 3; + + case WGL_FULL_ACCELERATION_ARB: return 1; + case WGL_GENERIC_ACCELERATION_ARB: return 2; + case WGL_NO_ACCELERATION_ARB: return 3; + + case WGL_TYPE_RGBA_ARB: return 1; + case WGL_TYPE_RGBA_FLOAT_ATI: return 2; + case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: return 3; + case WGL_TYPE_COLORINDEX_ARB: return 4; + + default: return 100; + } +} + +struct compare_formats_ctx +{ + int attribs[128]; + UINT num_attribs; +}; + +static int compare_formats( void *arg, const void *a, const void *b ) +{ + const struct wgl_pixel_format *fmt_a = *(void **)a, *fmt_b = *(void **)b; + struct compare_formats_ctx *ctx = arg; + int val_a, val_b; + UINT i; + + if (!fmt_a) return 1; + if (!fmt_b) return -1; + + for (i = 0; i < ctx->num_attribs; ++i) + { + if (wgl_pixel_format_get_attrib( fmt_a, ctx->attribs[i], &val_a ) && + wgl_pixel_format_get_attrib( fmt_b, ctx->attribs[i], &val_b ) && + val_a != val_b) + { + switch (ctx->attribs[i]) + { + case WGL_ACCELERATION_ARB: + case WGL_SWAP_METHOD_ARB: + case WGL_PIXEL_TYPE_ARB: + return wgl_attrib_value_priority( val_a ) - + wgl_attrib_value_priority( val_b ); + default: + /* Smaller values first */ + return val_a - val_b; + } + } + } + + /* Maintain pixel format id order */ + return fmt_a - fmt_b; +} + +/*********************************************************************** + * wglChoosePixelFormatARB (OPENGL32.@) + */ +BOOL WINAPI wglChoosePixelFormatARB( HDC hdc, const int *attribs_int, const FLOAT *attribs_float, + UINT max_formats, int *formats, UINT *num_formats ) +{ + struct wgl_pixel_format *wgl_formats; + UINT i, num_wgl_formats, num_wgl_onscreen_formats; + const struct wgl_pixel_format **format_array; + struct compare_formats_ctx ctx = { 0 }; + + TRACE( "hdc %p, attribs_int %p, attribs_float %p, max_formats %u, formats %p, num_formats %p\n", + hdc, attribs_int, attribs_float, max_formats, formats, num_formats ); + + wgl_formats = get_pixel_formats( hdc, &num_wgl_formats, &num_wgl_onscreen_formats ); + + /* If the driver doesn't yet provide ARB attrib information in + * wgl_pixel_format, fall back to an explicit call. */ + if (num_wgl_formats && !wgl_formats[0].pixel_type) + { + struct wglChoosePixelFormatARB_params args = + { + .teb = NtCurrentTeb(), + .hdc = hdc, + .piAttribIList = attribs_int, + .pfAttribFList = attribs_float, + .nMaxFormats = max_formats, + .piFormats = formats, + .nNumFormats = num_formats + }; + NTSTATUS status; + + if ((status = UNIX_CALL( wglChoosePixelFormatARB, &args ))) + WARN( "wglChoosePixelFormatARB returned %#lx\n", status ); + + return args.ret; + } + + /* Initialize the format_array with (pointers to) all wgl formats */ + format_array = malloc( num_wgl_formats * sizeof(*format_array) ); + if (!format_array) return FALSE; + for (i = 0; i < num_wgl_formats; ++i) format_array[i] = &wgl_formats[i]; + + /* Remove formats that are not acceptable */ + for (i = 0; attribs_int && attribs_int[i]; i += 2) + { + if (ctx.num_attribs == ARRAY_SIZE(ctx.attribs)) { free( format_array ); return FALSE; } + else ctx.attribs[ctx.num_attribs++] = attribs_int[i]; + filter_format_array( format_array, num_wgl_formats, attribs_int[i], attribs_int[i + 1] ); + } + for (i = 0; attribs_float && attribs_float[i]; i += 2) + { + if (ctx.num_attribs == ARRAY_SIZE(ctx.attribs)) { free( format_array ); return FALSE; } + else ctx.attribs[ctx.num_attribs++] = attribs_float[i]; + filter_format_array( format_array, num_wgl_formats, attribs_float[i], attribs_float[i + 1] ); + } + + /* Arrange attributes in the order which we want to check them */ + qsort( ctx.attribs, ctx.num_attribs, sizeof(*ctx.attribs), compare_attribs ); + + /* Sort pixel formats based on the specified attributes */ + qsort_s( format_array, num_wgl_formats, sizeof(*format_array), compare_formats, &ctx ); + + /* Return the best max_formats format ids */ + *num_formats = 0; + for (i = 0; i < num_wgl_formats && i < max_formats && format_array[i]; ++i) + { + ++*num_formats; + formats[i] = format_array[i] - wgl_formats + 1; + } + + free( format_array ); + return TRUE; +} + INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *ppfd ) { struct wgl_pixel_format *formats;
From: Alexandros Frantzis alexandros.frantzis@collabora.com
The driver uses the default implementation provided by opengl32.dll. --- dlls/winex11.drv/opengl.c | 382 +------------------------------------- 1 file changed, 1 insertion(+), 381 deletions(-)
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 3979d31a334..5d914b74f0a 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -743,224 +743,6 @@ static const char *debugstr_fbconfig( GLXFBConfig fbconfig ) return wine_dbg_sprintf( "fbconfig %#x visual id %#x drawable type %#x", id, visual, drawable ); }
-static int ConvertAttribWGLtoGLX(const int* iWGLAttr, int* oGLXAttr, struct wgl_pbuffer* pbuf) { - int nAttribs = 0; - unsigned cur = 0; - int attr, pop; - int drawattrib = 0; - int nvfloatattrib = GLX_DONT_CARE; - int pixelattrib = GLX_DONT_CARE; - - /* The list of WGL attributes is allowed to be NULL. We don't return here for NULL - * because we need to do fixups for GLX_DRAWABLE_TYPE/GLX_RENDER_TYPE/GLX_FLOAT_COMPONENTS_NV. */ - while (iWGLAttr && 0 != iWGLAttr[cur]) { - attr = iWGLAttr[cur]; - TRACE("pAttr[%d] = %x\n", cur, attr); - pop = iWGLAttr[++cur]; - - switch (attr) { - case WGL_AUX_BUFFERS_ARB: - PUSH2(oGLXAttr, GLX_AUX_BUFFERS, pop); - TRACE("pAttr[%d] = GLX_AUX_BUFFERS: %d\n", cur, pop); - break; - case WGL_COLOR_BITS_ARB: - PUSH2(oGLXAttr, GLX_BUFFER_SIZE, pop); - TRACE("pAttr[%d] = GLX_BUFFER_SIZE: %d\n", cur, pop); - break; - case WGL_BLUE_BITS_ARB: - PUSH2(oGLXAttr, GLX_BLUE_SIZE, pop); - TRACE("pAttr[%d] = GLX_BLUE_SIZE: %d\n", cur, pop); - break; - case WGL_RED_BITS_ARB: - PUSH2(oGLXAttr, GLX_RED_SIZE, pop); - TRACE("pAttr[%d] = GLX_RED_SIZE: %d\n", cur, pop); - break; - case WGL_GREEN_BITS_ARB: - PUSH2(oGLXAttr, GLX_GREEN_SIZE, pop); - TRACE("pAttr[%d] = GLX_GREEN_SIZE: %d\n", cur, pop); - break; - case WGL_ALPHA_BITS_ARB: - PUSH2(oGLXAttr, GLX_ALPHA_SIZE, pop); - TRACE("pAttr[%d] = GLX_ALPHA_SIZE: %d\n", cur, pop); - break; - case WGL_DEPTH_BITS_ARB: - PUSH2(oGLXAttr, GLX_DEPTH_SIZE, pop); - TRACE("pAttr[%d] = GLX_DEPTH_SIZE: %d\n", cur, pop); - break; - case WGL_STENCIL_BITS_ARB: - PUSH2(oGLXAttr, GLX_STENCIL_SIZE, pop); - TRACE("pAttr[%d] = GLX_STENCIL_SIZE: %d\n", cur, pop); - break; - case WGL_DOUBLE_BUFFER_ARB: - PUSH2(oGLXAttr, GLX_DOUBLEBUFFER, pop); - TRACE("pAttr[%d] = GLX_DOUBLEBUFFER: %d\n", cur, pop); - break; - case WGL_STEREO_ARB: - PUSH2(oGLXAttr, GLX_STEREO, pop); - TRACE("pAttr[%d] = GLX_STEREO: %d\n", cur, pop); - break; - - case WGL_PIXEL_TYPE_ARB: - TRACE("pAttr[%d] = WGL_PIXEL_TYPE_ARB: %d\n", cur, pop); - switch (pop) { - case WGL_TYPE_COLORINDEX_ARB: pixelattrib = GLX_COLOR_INDEX_BIT; break ; - case WGL_TYPE_RGBA_ARB: pixelattrib = GLX_RGBA_BIT; break ; - /* This is the same as WGL_TYPE_RGBA_FLOAT_ATI but the GLX constants differ, only the ARB GLX one is widely supported so use that */ - case WGL_TYPE_RGBA_FLOAT_ATI: pixelattrib = GLX_RGBA_FLOAT_BIT; break ; - case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: pixelattrib = GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; break ; - default: - ERR("unexpected PixelType(%x)\n", pop); - } - break; - - case WGL_SUPPORT_GDI_ARB: - /* This flag is set in a pixel format */ - TRACE("pAttr[%d] = WGL_SUPPORT_GDI_ARB: %d\n", cur, pop); - break; - - case WGL_DRAW_TO_BITMAP_ARB: - /* This flag is set in a pixel format */ - TRACE("pAttr[%d] = WGL_DRAW_TO_BITMAP_ARB: %d\n", cur, pop); - break; - - case WGL_DRAW_TO_WINDOW_ARB: - TRACE("pAttr[%d] = WGL_DRAW_TO_WINDOW_ARB: %d\n", cur, pop); - /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */ - if (pop) { - drawattrib |= GLX_WINDOW_BIT; - } - break; - - case WGL_DRAW_TO_PBUFFER_ARB: - TRACE("pAttr[%d] = WGL_DRAW_TO_PBUFFER_ARB: %d\n", cur, pop); - /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */ - if (pop) { - drawattrib |= GLX_PBUFFER_BIT; - } - break; - - case WGL_ACCELERATION_ARB: - /* This flag is set in a pixel format */ - TRACE("pAttr[%d] = WGL_ACCELERATION_ARB: %d\n", cur, pop); - break; - - case WGL_SUPPORT_OPENGL_ARB: - /** nothing to do, if we are here, supposing support Accelerated OpenGL */ - TRACE("pAttr[%d] = WGL_SUPPORT_OPENGL_ARB: %d\n", cur, pop); - break; - - case WGL_SWAP_METHOD_ARB: - TRACE("pAttr[%d] = WGL_SWAP_METHOD_ARB: %#x\n", cur, pop); - if (has_swap_method) - { - switch (pop) - { - case WGL_SWAP_EXCHANGE_ARB: - pop = GLX_SWAP_EXCHANGE_OML; - break; - case WGL_SWAP_COPY_ARB: - pop = GLX_SWAP_COPY_OML; - break; - case WGL_SWAP_UNDEFINED_ARB: - pop = GLX_SWAP_UNDEFINED_OML; - break; - default: - ERR("Unexpected swap method %#x.\n", pop); - pop = GLX_DONT_CARE; - } - PUSH2(oGLXAttr, GLX_SWAP_METHOD_OML, pop); - } - else - { - WARN("GLX_OML_swap_method not supported, ignoring attribute.\n"); - } - break; - - case WGL_PBUFFER_LARGEST_ARB: - PUSH2(oGLXAttr, GLX_LARGEST_PBUFFER, pop); - TRACE("pAttr[%d] = GLX_LARGEST_PBUFFER: %x\n", cur, pop); - break; - - case WGL_SAMPLE_BUFFERS_ARB: - PUSH2(oGLXAttr, GLX_SAMPLE_BUFFERS_ARB, pop); - TRACE("pAttr[%d] = GLX_SAMPLE_BUFFERS_ARB: %x\n", cur, pop); - break; - - case WGL_SAMPLES_ARB: - PUSH2(oGLXAttr, GLX_SAMPLES_ARB, pop); - TRACE("pAttr[%d] = GLX_SAMPLES_ARB: %x\n", cur, pop); - break; - - case WGL_TEXTURE_FORMAT_ARB: - case WGL_TEXTURE_TARGET_ARB: - case WGL_MIPMAP_TEXTURE_ARB: - TRACE("WGL_render_texture Attributes: %x as %x\n", iWGLAttr[cur - 1], iWGLAttr[cur]); - if (NULL == pbuf) { - ERR("trying to use GLX_Pbuffer Attributes without Pbuffer (was %x)\n", iWGLAttr[cur]); - } - if (!use_render_texture_emulation) { - if (WGL_NO_TEXTURE_ARB != pop) { - ERR("trying to use WGL_render_texture Attributes without support (was %x)\n", iWGLAttr[cur]); - return -1; /** error: don't support it */ - } else { - drawattrib |= GLX_PBUFFER_BIT; - } - } - break ; - case WGL_FLOAT_COMPONENTS_NV: - nvfloatattrib = pop; - TRACE("pAttr[%d] = WGL_FLOAT_COMPONENTS_NV: %x\n", cur, nvfloatattrib); - break ; - case WGL_BIND_TO_TEXTURE_DEPTH_NV: - case WGL_BIND_TO_TEXTURE_RGB_ARB: - case WGL_BIND_TO_TEXTURE_RGBA_ARB: - case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV: - case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV: - case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV: - case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV: - /** cannot be converted, see direct handling on - * - wglGetPixelFormatAttribivARB - * TODO: wglChoosePixelFormat - */ - break ; - case WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT: - PUSH2(oGLXAttr, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, pop); - TRACE("pAttr[%d] = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: %x\n", cur, pop); - break ; - - case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: - PUSH2(oGLXAttr, GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT, pop); - TRACE("pAttr[%d] = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT: %x\n", cur, pop); - break ; - default: - FIXME("unsupported %x WGL Attribute\n", attr); - break; - } - ++cur; - } - - /* By default glXChooseFBConfig defaults to GLX_WINDOW_BIT. wglChoosePixelFormatARB searches through - * all formats. Unless drawattrib is set to a non-zero value override it with GLX_DONT_CARE, so that - * pixmap and pbuffer formats appear as well. */ - if (!drawattrib) drawattrib = GLX_DONT_CARE; - PUSH2(oGLXAttr, GLX_DRAWABLE_TYPE, drawattrib); - TRACE("pAttr[?] = GLX_DRAWABLE_TYPE: %#x\n", drawattrib); - - /* By default glXChooseFBConfig uses GLX_RGBA_BIT as the default value. Since wglChoosePixelFormatARB - * searches in all formats we have to do the same. For this reason we set GLX_RENDER_TYPE to - * GLX_DONT_CARE unless it is overridden. */ - PUSH2(oGLXAttr, GLX_RENDER_TYPE, pixelattrib); - TRACE("pAttr[?] = GLX_RENDER_TYPE: %#x\n", pixelattrib); - - /* Set GLX_FLOAT_COMPONENTS_NV all the time */ - if (has_extension(glxExtensions, "GLX_NV_float_buffer")) { - PUSH2(oGLXAttr, GLX_FLOAT_COMPONENTS_NV, nvfloatattrib); - TRACE("pAttr[?] = GLX_FLOAT_COMPONENTS_NV: %#x\n", nvfloatattrib); - } - - return nAttribs; -} - static int get_render_type_from_fbconfig(Display *display, GLXFBConfig fbconfig) { int render_type, render_type_bit; @@ -2592,168 +2374,6 @@ static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int return ret; }
-struct choose_pixel_format_arb_format -{ - int format; - int original_index; - struct wgl_pixel_format pf; - int depth, stencil; -}; - -static int compare_formats(const void *a, const void *b) -{ - /* Order formats so that onscreen formats go first. Then, if no depth bits requested, - * prioritize formats with smaller depth within the original sort order with respect to - * other attributes. */ - const struct choose_pixel_format_arb_format *fmt_a = a, *fmt_b = b; - BOOL offscreen_a, offscreen_b; - - offscreen_a = fmt_a->format > nb_onscreen_formats; - offscreen_b = fmt_b->format > nb_onscreen_formats; - - if (offscreen_a != offscreen_b) - return offscreen_a - offscreen_b; - if (memcmp(&fmt_a->pf.pfd, &fmt_b->pf.pfd, sizeof(fmt_a->pf.pfd))) - return fmt_a->original_index - fmt_b->original_index; - if (fmt_a->depth != fmt_b->depth) - return fmt_a->depth - fmt_b->depth; - if (fmt_a->stencil != fmt_b->stencil) - return fmt_a->stencil - fmt_b->stencil; - - return fmt_a->original_index - fmt_b->original_index; -} - -/** - * X11DRV_wglChoosePixelFormatARB - * - * WGL_ARB_pixel_format: wglChoosePixelFormatARB - */ -static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, - UINT nMaxFormats, int *piFormats, UINT *nNumFormats ) -{ - struct choose_pixel_format_arb_format *formats; - int it, i, format_count; - BYTE depth_bits = 0; - GLXFBConfig* cfgs; - DWORD dwFlags = 0; - int attribs[256]; - int nAttribs = 0; - int nCfgs = 0; - int fmt_id; - - TRACE("(%p, %p, %p, %d, %p, %p): hackish\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); - if (NULL != pfAttribFList) { - FIXME("unused pfAttribFList\n"); - } - - nAttribs = ConvertAttribWGLtoGLX(piAttribIList, attribs, NULL); - if (-1 == nAttribs) { - WARN("Cannot convert WGL to GLX attributes\n"); - return GL_FALSE; - } - PUSH1(attribs, None); - - /* There is no 1:1 mapping between GLX and WGL formats because we duplicate some GLX formats for bitmap rendering (see get_formats). - * Flags like PFD_SUPPORT_GDI, PFD_DRAW_TO_BITMAP and others are a property of the pixel format. We don't query these attributes - * using glXChooseFBConfig but we filter the result of glXChooseFBConfig later on. - */ - for(i=0; piAttribIList[i] != 0; i+=2) - { - switch(piAttribIList[i]) - { - case WGL_DRAW_TO_BITMAP_ARB: - if(piAttribIList[i+1]) - dwFlags |= PFD_DRAW_TO_BITMAP; - break; - case WGL_ACCELERATION_ARB: - switch(piAttribIList[i+1]) - { - case WGL_NO_ACCELERATION_ARB: - dwFlags |= PFD_GENERIC_FORMAT; - break; - case WGL_GENERIC_ACCELERATION_ARB: - dwFlags |= PFD_GENERIC_ACCELERATED; - break; - case WGL_FULL_ACCELERATION_ARB: - /* Nothing to do */ - break; - } - break; - case WGL_SUPPORT_GDI_ARB: - if(piAttribIList[i+1]) - dwFlags |= PFD_SUPPORT_GDI; - break; - case WGL_DEPTH_BITS_ARB: - depth_bits = piAttribIList[i+1]; - break; - - } - } - - /* Search for FB configurations matching the requirements in attribs */ - cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), attribs, &nCfgs); - if (NULL == cfgs) { - WARN("Compatible Pixel Format not found\n"); - return GL_FALSE; - } - - if (!(formats = malloc( nCfgs * sizeof(*formats) ))) - { - ERR("No memory.\n"); - XFree(cfgs); - return GL_FALSE; - } - - format_count = 0; - for (it = 0; it < nCfgs; ++it) - { - struct choose_pixel_format_arb_format *format; - - if (pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id)) - { - ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); - continue; - } - - for (i = 0; i < nb_pixel_formats; ++i) - if (pixel_formats[i].fmt_id == fmt_id) - break; - - if (i == nb_pixel_formats) - continue; - if ((pixel_formats[i].dwFlags & dwFlags) != dwFlags) - continue; - - format = &formats[format_count]; - format->format = i + 1; - format->original_index = it; - - memset(&format->pf, 0, sizeof(format->pf)); - if (!describe_pixel_format(format->format, &format->pf)) - ERR("describe_pixel_format failed, format %d.\n", format->format); - - format->depth = format->pf.pfd.cDepthBits; - format->stencil = format->pf.pfd.cStencilBits; - if (!depth_bits && !(format->pf.pfd.dwFlags & PFD_GENERIC_FORMAT)) - { - format->pf.pfd.cDepthBits = 0; - format->pf.pfd.cStencilBits = 0; - } - - ++format_count; - } - - qsort(formats, format_count, sizeof(*formats), compare_formats); - - *nNumFormats = min(nMaxFormats, format_count); - for (i = 0; i < *nNumFormats; ++i) - piFormats[i] = formats[i].format; - - free( formats ); - XFree(cfgs); - return GL_TRUE; -} - /** * X11DRV_wglBindTexImageARB * @@ -3012,7 +2632,7 @@ static void X11DRV_WineGL_LoadExtensions(void) }
register_extension( "WGL_ARB_pixel_format" ); - opengl_funcs.ext.p_wglChoosePixelFormatARB = X11DRV_wglChoosePixelFormatARB; + opengl_funcs.ext.p_wglChoosePixelFormatARB = (void *)1; /* never called */ opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */ opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Populate wgl_pixel_format ARB attributes to enable the default implementation of WGL_ARB_pixel_format. --- dlls/winewayland.drv/opengl.c | 77 +++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 3cb8b1e8a0d..e714b2cb952 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -707,14 +707,17 @@ static BOOL wayland_wglSwapIntervalEXT(int interval)
static void describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt) { - EGLint value; + EGLint value, surface_type; PIXELFORMATDESCRIPTOR *pfd = &fmt->pfd;
- memset(pfd, 0, sizeof(*pfd)); + /* If we can't get basic information, there is no point continuing */ + if (!p_eglGetConfigAttrib(egl_display, config, EGL_SURFACE_TYPE, &surface_type)) return; + + memset(fmt, 0, sizeof(*fmt)); pfd->nSize = sizeof(*pfd); pfd->nVersion = 1; - pfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | - PFD_SUPPORT_COMPOSITION; + pfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SUPPORT_COMPOSITION; + if (surface_type & EGL_WINDOW_BIT) pfd->dwFlags |= PFD_DRAW_TO_WINDOW; pfd->iPixelType = PFD_TYPE_RGBA; pfd->iLayerType = PFD_MAIN_PLANE;
@@ -722,6 +725,9 @@ static void describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt value = 0; \ p_eglGetConfigAttrib(egl_display, config, attrib, &value); \ pfd->field = value; +#define SET_ATTRIB_ARB(field, attrib) \ + if (!p_eglGetConfigAttrib(egl_display, config, attrib, &value)) value = -1; \ + fmt->field = value;
/* Although the documentation describes cColorBits as excluding alpha, real * drivers tend to return the full pixel size, so do the same. */ @@ -743,7 +749,65 @@ static void describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt SET_ATTRIB(cDepthBits, EGL_DEPTH_SIZE); SET_ATTRIB(cStencilBits, EGL_STENCIL_SIZE);
+ fmt->swap_method = WGL_SWAP_UNDEFINED_ARB; + + if (p_eglGetConfigAttrib(egl_display, config, EGL_TRANSPARENT_TYPE, &value)) + { + switch (value) + { + case EGL_TRANSPARENT_RGB: fmt->transparent = GL_TRUE; break; + case EGL_NONE: fmt->transparent = GL_FALSE; break; + default: + ERR("unexpected transparency type 0x%x\n", value); + fmt->transparent = -1; + break; + } + } + else fmt->transparent = -1; + + /* TODO: Support floating point pixel components */ + fmt->pixel_type = WGL_TYPE_RGBA_ARB; + + fmt->draw_to_pbuffer = !!(surface_type & EGL_PBUFFER_BIT); + SET_ATTRIB_ARB(max_pbuffer_pixels, EGL_MAX_PBUFFER_PIXELS); + SET_ATTRIB_ARB(max_pbuffer_width, EGL_MAX_PBUFFER_WIDTH); + SET_ATTRIB_ARB(max_pbuffer_height, EGL_MAX_PBUFFER_HEIGHT); + + if (p_eglGetConfigAttrib(egl_display, config, EGL_TRANSPARENT_RED_VALUE, &value)) + { + fmt->transparent_red_value_valid = GL_TRUE; + fmt->transparent_red_value = value; + } + if (p_eglGetConfigAttrib(egl_display, config, EGL_TRANSPARENT_GREEN_VALUE, &value)) + { + fmt->transparent_green_value_valid = GL_TRUE; + fmt->transparent_green_value = value; + } + if (p_eglGetConfigAttrib(egl_display, config, EGL_TRANSPARENT_BLUE_VALUE, &value)) + { + fmt->transparent_blue_value_valid = GL_TRUE; + fmt->transparent_blue_value = value; + } + fmt->transparent_alpha_value_valid = GL_TRUE; + fmt->transparent_alpha_value = 0; + fmt->transparent_index_value_valid = GL_TRUE; + fmt->transparent_index_value = 0; + + SET_ATTRIB_ARB(sample_buffers, EGL_SAMPLE_BUFFERS); + SET_ATTRIB_ARB(samples, EGL_SAMPLES); + + SET_ATTRIB_ARB(bind_to_texture_rgb, EGL_BIND_TO_TEXTURE_RGB); + SET_ATTRIB_ARB(bind_to_texture_rgba, EGL_BIND_TO_TEXTURE_RGBA); + fmt->bind_to_texture_rectangle_rgb = fmt->bind_to_texture_rgb; + fmt->bind_to_texture_rectangle_rgba = fmt->bind_to_texture_rgba; + + /* TODO: Support SRGB surfaces and enable the attribute */ + fmt->framebuffer_srgb_capable = GL_FALSE; + + fmt->float_components = GL_FALSE; + #undef SET_ATTRIB +#undef SET_ATTRIB_ARB }
static BOOL has_opengl(void); @@ -827,6 +891,11 @@ static BOOL init_opengl_funcs(void) opengl_funcs.ext.p_wglGetSwapIntervalEXT = wayland_wglGetSwapIntervalEXT; opengl_funcs.ext.p_wglSwapIntervalEXT = wayland_wglSwapIntervalEXT;
+ register_extension("WGL_ARB_pixel_format"); + opengl_funcs.ext.p_wglChoosePixelFormatARB = (void *)1; /* never called */ + opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */ + opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */ + return TRUE; }
From: Alexandros Frantzis alexandros.frantzis@collabora.com
--- dlls/winewayland.drv/opengl.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index e714b2cb952..994154968b3 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -49,6 +49,7 @@ static EGLDisplay egl_display; static char wgl_extensions[4096]; static EGLConfig *egl_configs; static int num_egl_configs; +static BOOL has_egl_ext_pixel_format_float;
#define USE_GL_FUNC(name) #name, static const char *opengl_func_names[] = { ALL_WGL_FUNCS }; @@ -765,8 +766,24 @@ static void describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt } else fmt->transparent = -1;
- /* TODO: Support floating point pixel components */ - fmt->pixel_type = WGL_TYPE_RGBA_ARB; + if (!has_egl_ext_pixel_format_float) fmt->pixel_type = WGL_TYPE_RGBA_ARB; + else if (p_eglGetConfigAttrib(egl_display, config, EGL_COLOR_COMPONENT_TYPE_EXT, &value)) + { + switch (value) + { + case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT: + fmt->pixel_type = WGL_TYPE_RGBA_ARB; + break; + case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT: + fmt->pixel_type = WGL_TYPE_RGBA_FLOAT_ARB; + break; + default: + ERR("unexpected color component type 0x%x\n", value); + fmt->pixel_type = -1; + break; + } + } + else fmt->pixel_type = -1;
fmt->draw_to_pbuffer = !!(surface_type & EGL_PBUFFER_BIT); SET_ATTRIB_ARB(max_pbuffer_pixels, EGL_MAX_PBUFFER_PIXELS); @@ -896,6 +913,12 @@ static BOOL init_opengl_funcs(void) opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */ opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
+ if (has_egl_ext_pixel_format_float) + { + register_extension("WGL_ARB_pixel_format_float"); + register_extension("WGL_ATI_pixel_format_float"); + } + return TRUE; }
@@ -1030,6 +1053,8 @@ static void init_opengl(void) REQUIRE_EXT(EGL_KHR_no_config_context); #undef REQUIRE_EXT
+ has_egl_ext_pixel_format_float = has_extension(egl_exts, "EGL_EXT_pixel_format_float"); + if (!init_opengl_funcs()) goto err; if (!init_egl_configs()) goto err;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146576
Your paranoid android.
=== debian11b (64 bit WoW report) ===
d3d10core: d3d10core: Timeout
Rémi Bernon (@rbernon) commented about dlls/opengl32/wgl.c:
- case WGL_STENCIL_BITS_ARB: return 9;
- case WGL_ACCUM_BITS_ARB: return 10;
- case WGL_DOUBLE_BUFFER_ARB: return 11;
- case WGL_SWAP_METHOD_ARB: return 12;
- default: return 100;
- }
+}
+static int compare_attribs( const void *a, const void *b ) +{
- int prio_a = wgl_attrib_sort_priority( *(int *)a );
- int prio_b = wgl_attrib_sort_priority( *(int *)b );
- if (prio_a == prio_b) return 0;
- else if (prio_a < prio_b) return -1;
- else return 1;
Any reason not to do `return prio_a - prio_b`?
Rémi Bernon (@rbernon) commented about dlls/opengl32/wgl.c:
if ((status = UNIX_CALL( wglChoosePixelFormatARB, &args )))
WARN( "wglChoosePixelFormatARB returned %#lx\n", status );
return args.ret;
- }
- /* Initialize the format_array with (pointers to) all wgl formats */
- format_array = malloc( num_wgl_formats * sizeof(*format_array) );
- if (!format_array) return FALSE;
- for (i = 0; i < num_wgl_formats; ++i) format_array[i] = &wgl_formats[i];
- /* Remove formats that are not acceptable */
- for (i = 0; attribs_int && attribs_int[i]; i += 2)
- {
if (ctx.num_attribs == ARRAY_SIZE(ctx.attribs)) { free( format_array ); return FALSE; }
What about either making this an assert, or (especially if it's possible to have duplicate attributes), counting them upfront and allocating the context dynamically?
Regarding the format ordering, I think you should enforce a couple of attributes to sort by default. For instance `WGL_ACCELERATION_ARB` seems to be appropriate, so that non-accelerated formats always go last, unless explicitly requested. Similarly it seems to me that native avoids offering accum buffer if possible, and they should be put to lower priority by default.
Then, WGL_COLOR_BITS_ARB may also need some tweaking. If it is specified you will sort the formats by increasing color bits, and it will offer 16bpp formats first if WGL_COLOR_BITS_ARB value is 16. Native seems to always prefer 24/32bit or higher here (native AMD doesn't even have accelerated 16bpp but NVIDIA does).
On Thu Jun 27 12:25:02 2024 +0000, Rémi Bernon wrote:
Regarding the format ordering, I think you should enforce a couple of attributes to sort by default. For instance `WGL_ACCELERATION_ARB` seems to be appropriate, so that non-accelerated formats always go last, unless explicitly requested. Similarly it seems to me that native avoids offering accum buffer if possible, and they should be put to lower priority by default. Then, WGL_COLOR_BITS_ARB may also need some tweaking. If it is specified you will sort the formats by increasing color bits, and it will offer 16bpp formats first if WGL_COLOR_BITS_ARB value is 16. Native seems to always prefer 24/32bit or higher here (native AMD doesn't even have accelerated 16bpp but NVIDIA does).
Ack. I remember you had made an adapted version of wglchoose. Do you still have that available somewhere so I can rerun on testbot, because the NVIDIA results (linked from https://gitlab.winehq.org/wine/wine/-/merge_requests/5388#note_67583) are no longer available.
On Thu Jun 27 12:25:02 2024 +0000, Alexandros Frantzis wrote:
Ack. I remember you had made an adapted version of wglchoose. Do you still have that available somewhere so I can rerun on testbot, because the NVIDIA results (linked from https://gitlab.winehq.org/wine/wine/-/merge_requests/5388#note_67583) are no longer available.
I have it here https://gitlab.winehq.org/rbernon/wine/-/commit/8b0805476a2992ddf7a7fbab9ee7..., though it depends on a couple of other things I have in this branch.
I ran this earlier today here if that's easier maybe: https://testbot.winehq.org/JobDetails.pl?Key=146608&f101=exe64.report&am...