[PATCH v2 0/4] MR5933: opengl32: Add default implementation for wglChoosePixelFormatARB.
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. -- v2: winewayland: Support WGL_ARB_pixel_format_float. winewayland: Support WGL_ARB_pixel_format. winex11: Remove driver wglChoosePixelFormatARB implementation. opengl32: Add default implementation for wglChoosePixelFormatARB. https://gitlab.winehq.org/wine/wine/-/merge_requests/5933
From: Alexandros Frantzis <alexandros.frantzis(a)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 | 283 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 285 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..19d989e44fc 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include <assert.h> #include <stdarg.h> #include <stdlib.h> #include <math.h> @@ -492,6 +493,288 @@ static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int return valid; } +enum attrib_match +{ + ATTRIB_MATCH_INVALID = -1, + 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; + case WGL_NUMBER_PIXEL_FORMATS_ARB: + case WGL_RED_SHIFT_ARB: + case WGL_GREEN_SHIFT_ARB: + case WGL_BLUE_SHIFT_ARB: + case WGL_ALPHA_SHIFT_ARB: + case WGL_TRANSPARENT_ARB: + case WGL_TRANSPARENT_RED_VALUE_ARB: + case WGL_TRANSPARENT_GREEN_VALUE_ARB: + case WGL_TRANSPARENT_BLUE_VALUE_ARB: + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: + case WGL_TRANSPARENT_INDEX_VALUE_ARB: + return ATTRIB_MATCH_IGNORE; + default: + return ATTRIB_MATCH_INVALID; + } +} + +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; + + assert(match != ATTRIB_MATCH_INVALID); + + 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_ACCUM_BITS_ARB: return 5; + case WGL_PIXEL_TYPE_ARB: return 6; + case WGL_ALPHA_BITS_ARB: return 7; + case WGL_AUX_BUFFERS_ARB: return 8; + case WGL_DEPTH_BITS_ARB: return 9; + case WGL_STENCIL_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 ) +{ + return wgl_attrib_sort_priority( *(int *)a ) - wgl_attrib_sort_priority( *(int *)b ); +} + +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[256]; + 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 attrib, val_a, val_b; + UINT i; + + if (!fmt_a) return 1; + if (!fmt_b) return -1; + + for (i = 0; i < ctx->num_attribs; ++i) + { + attrib = ctx->attribs[2 * i]; + if (wgl_pixel_format_get_attrib( fmt_a, attrib, &val_a ) && + wgl_pixel_format_get_attrib( fmt_b, attrib, &val_b ) && + val_a != val_b) + { + switch (attrib) + { + 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 ); + case WGL_COLOR_BITS_ARB: + /* Prefer 32bpp over other values */ + if (val_a >= 32 && val_b >= 32) return val_a - val_b; + else return val_b - val_a; + default: + /* Smaller values first */ + return val_a - val_b; + } + } + } + + /* Maintain pixel format id order */ + return fmt_a - fmt_b; +} + +static void compare_formats_ctx_set_attrib( struct compare_formats_ctx *ctx, + int attrib, int value ) +{ + UINT i; + + /* Overwrite attribute if it exists already */ + for (i = 0; i < ctx->num_attribs; ++i) + if (ctx->attribs[2 * i] == attrib) break; + + assert(i < ARRAY_SIZE(ctx->attribs) / 2); + + ctx->attribs[2 * i] = attrib; + ctx->attribs[2 * i + 1] = value; + if (i == ctx->num_attribs) ++ctx->num_attribs; +} + +/*********************************************************************** + * 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; + } + + /* Gather, validate and deduplicate all attributes */ + for (i = 0; attribs_int && attribs_int[i]; i += 2) + { + if (wgl_attrib_match_criteria( attribs_int[i] ) == ATTRIB_MATCH_INVALID) return FALSE; + compare_formats_ctx_set_attrib( &ctx, attribs_int[i], attribs_int[i + 1] ); + } + for (i = 0; attribs_float && attribs_float[i]; i += 2) + { + if (wgl_attrib_match_criteria( attribs_float[i] ) == ATTRIB_MATCH_INVALID) return FALSE; + compare_formats_ctx_set_attrib( &ctx, attribs_float[i], attribs_float[i + 1] ); + } + + /* 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; i < ctx.num_attribs; ++i) + filter_format_array( format_array, num_wgl_formats, ctx.attribs[2 * i], + ctx.attribs[2 * i + 1] ); + + /* Some attributes we always want to sort by (values don't matter for sorting) */ + compare_formats_ctx_set_attrib( &ctx, WGL_ACCELERATION_ARB, 0 ); + compare_formats_ctx_set_attrib( &ctx, WGL_COLOR_BITS_ARB, 0 ); + compare_formats_ctx_set_attrib( &ctx, WGL_ACCUM_BITS_ARB, 0 ); + + /* Arrange attributes in the order which we want to check them */ + qsort( ctx.attribs, ctx.num_attribs, 2 * 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; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5933
From: Alexandros Frantzis <alexandros.frantzis(a)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 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5933
From: Alexandros Frantzis <alexandros.frantzis(a)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; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5933
From: Alexandros Frantzis <alexandros.frantzis(a)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; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5933
On Fri Jun 28 12:13:28 2024 +0000, Alexandros Frantzis wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5933/diffs?diff_id=119918&start_sha=53e08c7938cec9e6899c8b820e3dbda8a274dea8#50d0467261bda62e69cb439805b6af18beaf754b_599_610) No, changed in v2.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933#note_74661
On Fri Jun 28 12:13:29 2024 +0000, Alexandros Frantzis wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5933/diffs?diff_id=119918&start_sha=53e08c7938cec9e6899c8b820e3dbda8a274dea8#50d0467261bda62e69cb439805b6af18beaf754b_709_736) I have kept the static allocation, added an assertion but I am now deduplicating attributes, keeping the last value specified.
This matches AMD and Intel behavior, but NVIDIA acts more erratically when it gets duplicates: for numerical attributes it seems to [apply the stricter constraint](https://testbot.winehq.org/JobDetails.pl?Key=146638&f101=exe64.report&f102=e...) but for other kinds of attributes it sometimes prefers one of the values and it [works](https://testbot.winehq.org/JobDetails.pl?Key=146637&f101=exe64.report&f102=e...) but other times it just [fails](https://testbot.winehq.org/JobDetails.pl?Key=146642&f102=exe64.report#k101). Note that the above runs are using an adapted version of wglchoose.exe that passes duplicate attributes to the WGL attrib list (the previous version deduplicated itself before passing). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933#note_74662
v2: * Deduplicate passed attributes keeping the last specified value. * Always sort results preferring better acceleration, fewer accum buffer bits, and 32bpp color bits. * Fail if the attribute list contains an attribute we don't know about (matches AMD and Intel, NVIDIA succeeds with 0 results, see https://testbot.winehq.org/JobDetails.pl?Key=146647). I am not yet setting an error value, although Intel returns our old friend 0xC007000D and AMD nothing as usual. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933#note_74664
On Thu Jun 27 13:41:13 2024 +0000, Rémi Bernon wrote:
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&f102=e... I have implemented a form of the above suggestions in v2, sorting by default on WGL_ACCELERATION_ARB, WGL_ACCUM_BITS_ARB (also decreased sort priority) and WGL_COLOR_BITS_ARB (biasing towards 32bpp).
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933#note_74663
just a quick question at what part of the wayland patch is clipboard support sorry if this is not the place to ask this question I just didn't find any direct way to ask the question -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933#note_74775
On Mon Jul 1 06:09:07 2024 +0000, beh 591 wrote:
just a quick question at what part of the wayland patch is clipboard support sorry if this is not the place to ask this question I just didn't find any direct way to ask the question At this point, the order of Wayland driver feature upstreaming does not follow a fixed plan, so I can't really provide a particular part number. The best I can answer is "hopefully later this year".
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933#note_74783
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5933
participants (4)
-
Alexandros Frantzis -
Alexandros Frantzis (@afrantzis) -
beh 591 (@beh_591) -
Rémi Bernon