From: Alexandros Frantzis alexandros.frantzis@collabora.com
Extend the wgl_pixel_format struct with extra fields required to implement wglGetPixelFormatAttribivARB in opengl32.dll. The default implementation will be used automatically if the driver populates the extra fields. --- dlls/opengl32/make_opengl | 26 +++++ dlls/opengl32/thunks.c | 10 +- dlls/opengl32/wgl.c | 197 +++++++++++++++++++++++++++++++++++++- include/wine/wgl_driver.h | 27 +++++- 4 files changed, 249 insertions(+), 11 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index f1fddb6dcfa..42cc0c78ab3 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -181,6 +181,7 @@ my %manual_win_thunks = "wglGetExtensionsStringARB" => 1, "wglGetExtensionsStringEXT" => 1, "wglGetPixelFormat" => 1, + "wglGetPixelFormatAttribivARB" => 1, "wglGetProcAddress" => 1, "wglQueryCurrentRendererStringWINE" => 1, "wglQueryRendererStringWINE" => 1, @@ -884,6 +885,31 @@ print HEADER "struct wgl_pbuffer;\n\n"; print HEADER "struct wgl_pixel_format\n"; print HEADER "{\n"; print HEADER " PIXELFORMATDESCRIPTOR pfd;\n"; +print HEADER " int swap_method;\n"; +print HEADER " int transparent;\n"; +print HEADER " int pixel_type;\n"; +print HEADER " int draw_to_pbuffer;\n"; +print HEADER " int max_pbuffer_pixels;\n"; +print HEADER " int max_pbuffer_width;\n"; +print HEADER " int max_pbuffer_height;\n"; +print HEADER " int transparent_red_value;\n"; +print HEADER " int transparent_red_value_valid;\n"; +print HEADER " int transparent_green_value;\n"; +print HEADER " int transparent_green_value_valid;\n"; +print HEADER " int transparent_blue_value;\n"; +print HEADER " int transparent_blue_value_valid;\n"; +print HEADER " int transparent_alpha_value;\n"; +print HEADER " int transparent_alpha_value_valid;\n"; +print HEADER " int transparent_index_value;\n"; +print HEADER " int transparent_index_value_valid;\n"; +print HEADER " int sample_buffers;\n"; +print HEADER " int samples;\n"; +print HEADER " int bind_to_texture_rgb;\n"; +print HEADER " int bind_to_texture_rgba;\n"; +print HEADER " int bind_to_texture_rectangle_rgb;\n"; +print HEADER " int bind_to_texture_rectangle_rgba;\n"; +print HEADER " int framebuffer_srgb_capable;\n"; +print HEADER " int float_components;\n"; print HEADER "};\n\n";
print HEADER "struct opengl_funcs\n{\n"; diff --git a/dlls/opengl32/thunks.c b/dlls/opengl32/thunks.c index 49f32461de5..2bd1dd302ee 100644 --- a/dlls/opengl32/thunks.c +++ b/dlls/opengl32/thunks.c @@ -24226,15 +24226,6 @@ static BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int return args.ret; }
-static BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues ) -{ - struct wglGetPixelFormatAttribivARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .iPixelFormat = iPixelFormat, .iLayerPlane = iLayerPlane, .nAttributes = nAttributes, .piAttributes = piAttributes, .piValues = piValues }; - NTSTATUS status; - TRACE( "hdc %p, iPixelFormat %d, iLayerPlane %d, nAttributes %u, piAttributes %p, piValues %p\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues ); - if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args ))) WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status ); - return args.ret; -} - static int WINAPI wglGetSwapIntervalEXT(void) { struct wglGetSwapIntervalEXT_params args = { .teb = NtCurrentTeb() }; @@ -24340,6 +24331,7 @@ extern GLboolean WINAPI glUnmapNamedBufferEXT( GLuint buffer ); extern HDC WINAPI wglGetCurrentReadDCARB(void); extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc ); extern const char * WINAPI wglGetExtensionsStringEXT(void); +extern BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues ); extern const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute ); extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute ); const void *extension_procs[] = diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 903e402d0d0..8060cdfb1db 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -322,7 +322,9 @@ static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats, }
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error; - if (!(args.formats = malloc( sizeof(*args.formats) * args.num_formats ))) goto error; + /* Clear formats memory since not all drivers deal with all wgl_pixel_format + * fields at the moment. */ + if (!(args.formats = calloc( args.num_formats, sizeof(*args.formats) ))) goto error; args.max_formats = args.num_formats; if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
@@ -343,6 +345,135 @@ error: return NULL; }
+static BOOL wgl_attrib_uses_layer( int attrib ) +{ + switch (attrib) + { + case WGL_ACCELERATION_ARB: + case WGL_TRANSPARENT_ARB: + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_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: + case WGL_SUPPORT_OPENGL_ARB: + case WGL_DOUBLE_BUFFER_ARB: + case WGL_STEREO_ARB: + case WGL_PIXEL_TYPE_ARB: + case WGL_TYPE_COLORINDEX_ARB: + case WGL_COLOR_BITS_ARB: + case WGL_RED_BITS_ARB: + case WGL_RED_SHIFT_ARB: + case WGL_GREEN_BITS_ARB: + case WGL_GREEN_SHIFT_ARB: + case WGL_BLUE_BITS_ARB: + case WGL_BLUE_SHIFT_ARB: + case WGL_ALPHA_BITS_ARB: + case WGL_ALPHA_SHIFT_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: + return TRUE; + default: + return FALSE; + } +} + +static int wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int attrib ) +{ + switch (attrib) + { + case WGL_DRAW_TO_WINDOW_ARB: return !!(fmt->pfd.dwFlags & PFD_DRAW_TO_WINDOW); + case WGL_DRAW_TO_BITMAP_ARB: return !!(fmt->pfd.dwFlags & PFD_DRAW_TO_BITMAP); + case WGL_ACCELERATION_ARB: + if (fmt->pfd.dwFlags & PFD_GENERIC_ACCELERATED) + return WGL_GENERIC_ACCELERATION_ARB; + else if (fmt->pfd.dwFlags & PFD_GENERIC_FORMAT) + return WGL_NO_ACCELERATION_ARB; + else + return WGL_FULL_ACCELERATION_ARB; + break; + case WGL_NEED_PALETTE_ARB: return !!(fmt->pfd.dwFlags & PFD_NEED_PALETTE); + case WGL_NEED_SYSTEM_PALETTE_ARB: return !!(fmt->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE); + case WGL_SWAP_LAYER_BUFFERS_ARB: return !!(fmt->pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS); + case WGL_SWAP_METHOD_ARB: return fmt->swap_method; + case WGL_NUMBER_OVERLAYS_ARB: + case WGL_NUMBER_UNDERLAYS_ARB: + /* We don't support any overlays/underlays. */ + return 0; + case WGL_TRANSPARENT_ARB: return fmt->transparent; + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_ARB: + /* We support only a main plane at the moment which by definition + * shares the depth/stencil/accum buffers with itself. */ + return GL_TRUE; + case WGL_SUPPORT_GDI_ARB: return !!(fmt->pfd.dwFlags & PFD_SUPPORT_GDI); + case WGL_SUPPORT_OPENGL_ARB: return !!(fmt->pfd.dwFlags & PFD_SUPPORT_OPENGL); + case WGL_DOUBLE_BUFFER_ARB: return !!(fmt->pfd.dwFlags & PFD_SUPPORT_COMPOSITION); + case WGL_STEREO_ARB: return !!(fmt->pfd.dwFlags & PFD_STEREO); + case WGL_PIXEL_TYPE_ARB: return fmt->pixel_type; + case WGL_COLOR_BITS_ARB: return fmt->pfd.cColorBits; + case WGL_RED_BITS_ARB: return fmt->pfd.cRedBits; + case WGL_RED_SHIFT_ARB: return fmt->pfd.cRedShift; + case WGL_GREEN_BITS_ARB: return fmt->pfd.cGreenBits; + case WGL_GREEN_SHIFT_ARB: return fmt->pfd.cGreenShift; + case WGL_BLUE_BITS_ARB: return fmt->pfd.cBlueBits; + case WGL_BLUE_SHIFT_ARB: return fmt->pfd.cBlueShift; + case WGL_ALPHA_BITS_ARB: return fmt->pfd.cAlphaBits; + case WGL_ALPHA_SHIFT_ARB: return fmt->pfd.cAlphaShift; + case WGL_ACCUM_BITS_ARB: return fmt->pfd.cAccumBits; + case WGL_ACCUM_RED_BITS_ARB: return fmt->pfd.cAccumRedBits; + case WGL_ACCUM_GREEN_BITS_ARB: return fmt->pfd.cAccumGreenBits; + case WGL_ACCUM_BLUE_BITS_ARB: return fmt->pfd.cAccumBlueBits; + case WGL_ACCUM_ALPHA_BITS_ARB: return fmt->pfd.cAccumAlphaBits; + case WGL_DEPTH_BITS_ARB: return fmt->pfd.cDepthBits; + case WGL_STENCIL_BITS_ARB: return fmt->pfd.cStencilBits; + case WGL_AUX_BUFFERS_ARB: return fmt->pfd.cAuxBuffers; + case WGL_DRAW_TO_PBUFFER_ARB: return fmt->draw_to_pbuffer; + case WGL_MAX_PBUFFER_PIXELS_ARB: return fmt->max_pbuffer_pixels; + case WGL_MAX_PBUFFER_WIDTH_ARB: return fmt->max_pbuffer_width; + case WGL_MAX_PBUFFER_HEIGHT_ARB: return fmt->max_pbuffer_height; + case WGL_TRANSPARENT_RED_VALUE_ARB: return fmt->transparent_red_value; + case WGL_TRANSPARENT_GREEN_VALUE_ARB: return fmt->transparent_green_value; + case WGL_TRANSPARENT_BLUE_VALUE_ARB: return fmt->transparent_blue_value; + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: return fmt->transparent_alpha_value; + case WGL_TRANSPARENT_INDEX_VALUE_ARB: return fmt->transparent_index_value; + case WGL_SAMPLE_BUFFERS_ARB: return fmt->sample_buffers; + case WGL_SAMPLES_ARB: return fmt->samples; + case WGL_BIND_TO_TEXTURE_RGB_ARB: return fmt->bind_to_texture_rgb; + case WGL_BIND_TO_TEXTURE_RGBA_ARB: return fmt->bind_to_texture_rgba; + case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV: return fmt->bind_to_texture_rectangle_rgb; + case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV: return fmt->bind_to_texture_rectangle_rgba; + case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: return fmt->framebuffer_srgb_capable; + case WGL_FLOAT_COMPONENTS_NV: return fmt->float_components; + default: FIXME( "unsupported 0x%x WGL attribute\n", attrib ); + } + + return 0; +} + +static BOOL wgl_pixel_format_attrib_is_valid( const struct wgl_pixel_format *fmt, int attrib, int value ) +{ + switch (attrib) + { + case WGL_TRANSPARENT_RED_VALUE_ARB: return fmt->transparent_red_value_valid; + case WGL_TRANSPARENT_GREEN_VALUE_ARB: return fmt->transparent_green_value_valid; + case WGL_TRANSPARENT_BLUE_VALUE_ARB: return fmt->transparent_blue_value_valid; + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: return fmt->transparent_alpha_value_valid; + case WGL_TRANSPARENT_INDEX_VALUE_ARB: return fmt->transparent_index_value_valid; + default: return value != -1; + } +} + INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *ppfd ) { struct wgl_pixel_format *formats; @@ -360,6 +491,70 @@ INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDES return num_onscreen_formats; }
+/*********************************************************************** + * wglGetPixelFormatAttribivARB (OPENGL32.@) + */ +BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, + const int *piAttributes, int *piValues ) +{ + struct wgl_pixel_format *formats, *format; + UINT i, num_formats, num_onscreen_formats; + + TRACE( "hdc %p, iPixelFormat %d, iLayerPlane %d, nAttributes %u, piAttributes %p, piValues %p\n", + hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues ); + + formats = get_pixel_formats( hdc, &num_formats, &num_onscreen_formats ); + + /* If the driver doesn't yet provide ARB attrib information in + * wgl_pixel_format, fall back to an explicit call. */ + if (num_formats && !formats[0].pixel_type) + { + struct wglGetPixelFormatAttribivARB_params args = + { + .teb = NtCurrentTeb(), + .hdc = hdc, + .iPixelFormat = iPixelFormat, + .iLayerPlane = iLayerPlane, + .nAttributes = nAttributes, + .piAttributes = piAttributes, + .piValues = piValues + }; + NTSTATUS status; + + if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args ))) + WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status ); + + return args.ret; + } + + if (iPixelFormat > 0 && iPixelFormat - 1 < num_formats) + format = &formats[iPixelFormat - 1]; + else + format = NULL; + + for (i = 0; i < nAttributes; ++i) + { + int attrib = piAttributes[i]; + switch (attrib) + { + case WGL_NUMBER_PIXEL_FORMATS_ARB: + piValues[i] = num_formats; + break; + default: + if (format && (iLayerPlane == 0 || !wgl_attrib_uses_layer( attrib ))) + { + int val = wgl_pixel_format_get_attrib( format, attrib ); + if (!wgl_pixel_format_attrib_is_valid( format, attrib, val )) return FALSE; + piValues[i] = val; + } + else + return FALSE; + } + } + + return TRUE; +} + /*********************************************************************** * wglGetPixelFormat (OPENGL32.@) */ diff --git a/include/wine/wgl_driver.h b/include/wine/wgl_driver.h index b08ab4befde..2d0c2f562ab 100644 --- a/include/wine/wgl_driver.h +++ b/include/wine/wgl_driver.h @@ -7,7 +7,7 @@ #define WINE_GLAPI #endif
-#define WINE_WGL_DRIVER_VERSION 25 +#define WINE_WGL_DRIVER_VERSION 26
struct wgl_context; struct wgl_pbuffer; @@ -15,6 +15,31 @@ struct wgl_pbuffer; struct wgl_pixel_format { PIXELFORMATDESCRIPTOR pfd; + int swap_method; + int transparent; + int pixel_type; + int draw_to_pbuffer; + int max_pbuffer_pixels; + int max_pbuffer_width; + int max_pbuffer_height; + int transparent_red_value; + int transparent_red_value_valid; + int transparent_green_value; + int transparent_green_value_valid; + int transparent_blue_value; + int transparent_blue_value_valid; + int transparent_alpha_value; + int transparent_alpha_value_valid; + int transparent_index_value; + int transparent_index_value_valid; + int sample_buffers; + int samples; + int bind_to_texture_rgb; + int bind_to_texture_rgba; + int bind_to_texture_rectangle_rgb; + int bind_to_texture_rectangle_rgba; + int framebuffer_srgb_capable; + int float_components; };
struct opengl_funcs