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.
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 | 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;
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;
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.
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&am...) 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&am...) but other times it just [fails](https://testbot.winehq.org/JobDetails.pl?Key=146642&f102=exe64.report#k1...).
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).
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&am...
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).
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.
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
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".
This merge request was approved by Rémi Bernon.