-- v2: win32u: Add a nulldrv pbuffer stub implementation. winemac: Use the generic pbuffer implementation. winewayland: Use the generic pbuffer implementation. win32u: Introduce a generic pbuffer implementation from winex11. opengl32/tests: Add more pbuffer tests. win32u: Handle some pixel format initialization.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 148 ++++++++++++++++++++-------------- dlls/wineandroid.drv/opengl.c | 120 +++++++++++++-------------- dlls/winemac.drv/opengl.c | 48 +++++------ dlls/winewayland.drv/opengl.c | 42 +++++----- dlls/winex11.drv/opengl.c | 55 +++++-------- include/wine/opengl_driver.h | 2 + 6 files changed, 201 insertions(+), 214 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 36db698edae..9686f64ab2b 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -41,6 +41,59 @@ WINE_DEFAULT_DEBUG_CHANNEL(wgl);
static struct opengl_funcs *get_dc_funcs( HDC hdc, void *null_funcs );
+static const struct +{ + BYTE color_bits; + BYTE red_bits, red_shift; + BYTE green_bits, green_shift; + BYTE blue_bits, blue_shift; + BYTE alpha_bits, alpha_shift; + BYTE accum_bits; + BYTE depth_bits; + BYTE stencil_bits; +} pixel_formats[] = +{ + { 32, 8, 16, 8, 8, 8, 0, 8, 24, 16, 32, 8 }, + { 32, 8, 16, 8, 8, 8, 0, 8, 24, 16, 16, 8 }, + { 32, 8, 0, 8, 8, 8, 16, 8, 24, 16, 32, 8 }, + { 32, 8, 0, 8, 8, 8, 16, 8, 24, 16, 16, 8 }, + { 32, 8, 8, 8, 16, 8, 24, 8, 0, 16, 32, 8 }, + { 32, 8, 8, 8, 16, 8, 24, 8, 0, 16, 16, 8 }, + { 24, 8, 0, 8, 8, 8, 16, 0, 0, 16, 32, 8 }, + { 24, 8, 0, 8, 8, 8, 16, 0, 0, 16, 16, 8 }, + { 24, 8, 16, 8, 8, 8, 0, 0, 0, 16, 32, 8 }, + { 24, 8, 16, 8, 8, 8, 0, 0, 0, 16, 16, 8 }, + { 16, 5, 0, 6, 5, 5, 11, 0, 0, 16, 32, 8 }, + { 16, 5, 0, 6, 5, 5, 11, 0, 0, 16, 16, 8 }, +}; + +static void describe_pixel_format( int fmt, PIXELFORMATDESCRIPTOR *descr ) +{ + memset( descr, 0, sizeof(*descr) ); + descr->nSize = sizeof(*descr); + descr->nVersion = 1; + descr->dwFlags = PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP | PFD_GENERIC_FORMAT; + descr->iPixelType = PFD_TYPE_RGBA; + descr->cColorBits = pixel_formats[fmt - 1].color_bits; + descr->cRedBits = pixel_formats[fmt - 1].red_bits; + descr->cRedShift = pixel_formats[fmt - 1].red_shift; + descr->cGreenBits = pixel_formats[fmt - 1].green_bits; + descr->cGreenShift = pixel_formats[fmt - 1].green_shift; + descr->cBlueBits = pixel_formats[fmt - 1].blue_bits; + descr->cBlueShift = pixel_formats[fmt - 1].blue_shift; + descr->cAlphaBits = pixel_formats[fmt - 1].alpha_bits; + descr->cAlphaShift = pixel_formats[fmt - 1].alpha_shift; + descr->cAccumBits = pixel_formats[fmt - 1].accum_bits; + descr->cAccumRedBits = pixel_formats[fmt - 1].accum_bits / 4; + descr->cAccumGreenBits = pixel_formats[fmt - 1].accum_bits / 4; + descr->cAccumBlueBits = pixel_formats[fmt - 1].accum_bits / 4; + descr->cAccumAlphaBits = pixel_formats[fmt - 1].accum_bits / 4; + descr->cDepthBits = pixel_formats[fmt - 1].depth_bits; + descr->cStencilBits = pixel_formats[fmt - 1].stencil_bits; + descr->cAuxBuffers = 0; + descr->iLayerType = PFD_MAIN_PLANE; +} + static BOOL has_extension( const char *list, const char *ext ) { size_t len = strlen( ext ); @@ -220,59 +273,6 @@ static BOOL osmesa_make_current( struct wgl_context *context, void *bits, return ret; }
-static const struct -{ - BYTE color_bits; - BYTE red_bits, red_shift; - BYTE green_bits, green_shift; - BYTE blue_bits, blue_shift; - BYTE alpha_bits, alpha_shift; - BYTE accum_bits; - BYTE depth_bits; - BYTE stencil_bits; -} pixel_formats[] = -{ - { 32, 8, 16, 8, 8, 8, 0, 8, 24, 16, 32, 8 }, - { 32, 8, 16, 8, 8, 8, 0, 8, 24, 16, 16, 8 }, - { 32, 8, 0, 8, 8, 8, 16, 8, 24, 16, 32, 8 }, - { 32, 8, 0, 8, 8, 8, 16, 8, 24, 16, 16, 8 }, - { 32, 8, 8, 8, 16, 8, 24, 8, 0, 16, 32, 8 }, - { 32, 8, 8, 8, 16, 8, 24, 8, 0, 16, 16, 8 }, - { 24, 8, 0, 8, 8, 8, 16, 0, 0, 16, 32, 8 }, - { 24, 8, 0, 8, 8, 8, 16, 0, 0, 16, 16, 8 }, - { 24, 8, 16, 8, 8, 8, 0, 0, 0, 16, 32, 8 }, - { 24, 8, 16, 8, 8, 8, 0, 0, 0, 16, 16, 8 }, - { 16, 5, 0, 6, 5, 5, 11, 0, 0, 16, 32, 8 }, - { 16, 5, 0, 6, 5, 5, 11, 0, 0, 16, 16, 8 }, -}; - -static void describe_pixel_format( int fmt, PIXELFORMATDESCRIPTOR *descr ) -{ - memset( descr, 0, sizeof(*descr) ); - descr->nSize = sizeof(*descr); - descr->nVersion = 1; - descr->dwFlags = PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP | PFD_GENERIC_FORMAT; - descr->iPixelType = PFD_TYPE_RGBA; - descr->cColorBits = pixel_formats[fmt - 1].color_bits; - descr->cRedBits = pixel_formats[fmt - 1].red_bits; - descr->cRedShift = pixel_formats[fmt - 1].red_shift; - descr->cGreenBits = pixel_formats[fmt - 1].green_bits; - descr->cGreenShift = pixel_formats[fmt - 1].green_shift; - descr->cBlueBits = pixel_formats[fmt - 1].blue_bits; - descr->cBlueShift = pixel_formats[fmt - 1].blue_shift; - descr->cAlphaBits = pixel_formats[fmt - 1].alpha_bits; - descr->cAlphaShift = pixel_formats[fmt - 1].alpha_shift; - descr->cAccumBits = pixel_formats[fmt - 1].accum_bits; - descr->cAccumRedBits = pixel_formats[fmt - 1].accum_bits / 4; - descr->cAccumGreenBits = pixel_formats[fmt - 1].accum_bits / 4; - descr->cAccumBlueBits = pixel_formats[fmt - 1].accum_bits / 4; - descr->cAccumAlphaBits = pixel_formats[fmt - 1].accum_bits / 4; - descr->cDepthBits = pixel_formats[fmt - 1].depth_bits; - descr->cStencilBits = pixel_formats[fmt - 1].stencil_bits; - descr->cAuxBuffers = 0; - descr->iLayerType = PFD_MAIN_PLANE; -} - static BOOL osmesa_wglCopyContext( struct wgl_context *src, struct wgl_context *dst, UINT mask ) { FIXME( "not supported yet\n" ); @@ -377,6 +377,19 @@ static struct opengl_funcs *osmesa_get_wgl_driver(void)
#endif /* SONAME_LIBOSMESA */
+static UINT nulldrv_init_pixel_formats( UINT *onscreen_count ) +{ + *onscreen_count = ARRAY_SIZE(pixel_formats); + return ARRAY_SIZE(pixel_formats); +} + +static BOOL nulldrv_describe_pixel_format( int format, struct wgl_pixel_format *desc ) +{ + if (format <= 0 || format > ARRAY_SIZE(pixel_formats)) return FALSE; + describe_pixel_format( format, &desc->pfd ); + return TRUE; +} + static const char *nulldrv_init_wgl_extensions(void) { return ""; @@ -389,10 +402,13 @@ static BOOL nulldrv_set_pixel_format( HWND hwnd, int old_format, int new_format,
static const struct opengl_driver_funcs nulldrv_funcs = { + .p_init_pixel_formats = nulldrv_init_pixel_formats, + .p_describe_pixel_format = nulldrv_describe_pixel_format, .p_init_wgl_extensions = nulldrv_init_wgl_extensions, .p_set_pixel_format = nulldrv_set_pixel_format, }; static const struct opengl_driver_funcs *driver_funcs = &nulldrv_funcs; +static UINT formats_count, onscreen_count;
static char wgl_extensions[4096];
@@ -422,18 +438,13 @@ static int win32u_wglGetPixelFormat( HDC hdc ) else if ((dc = get_dc_ptr( hdc ))) { BOOL is_display = dc->is_display; - UINT total, onscreen; ret = dc->pixel_format; release_dc_ptr( dc );
- if (is_display && ret >= 0) - { - /* Offscreen formats can't be used with traditional WGL calls. As has been - * verified on Windows GetPixelFormat doesn't fail but returns 1. - */ - display_funcs->p_get_pixel_formats( NULL, 0, &total, &onscreen ); - if (ret > onscreen) ret = 1; - } + /* Offscreen formats can't be used with traditional WGL calls. As has been + * verified on Windows GetPixelFormat doesn't fail but returns 1. + */ + if (is_display && ret >= 0 && ret > onscreen_count) ret = 1; }
TRACE( "%p/%p -> %d\n", hdc, hwnd, ret ); @@ -481,6 +492,16 @@ static BOOL win32u_wglSetPixelFormatWINE( HDC hdc, int format ) return set_dc_pixel_format( hdc, format, TRUE ); }
+static void win32u_get_pixel_formats( struct wgl_pixel_format *formats, UINT max_formats, + UINT *num_formats, UINT *num_onscreen_formats ) +{ + UINT i = 0; + + if (formats) while (i < max_formats && driver_funcs->p_describe_pixel_format( i + 1, &formats[i] )) i++; + *num_formats = formats_count; + *num_onscreen_formats = onscreen_count; +} + static void memory_funcs_init(void) { memory_funcs = osmesa_get_wgl_driver(); @@ -500,8 +521,11 @@ static void display_funcs_init(void) ERR( "Failed to initialize the driver opengl functions, status %#x\n", status ); return; } + if (display_funcs && !(formats_count = driver_funcs->p_init_pixel_formats( &onscreen_count ))) display_funcs = NULL; if (!display_funcs) return;
+ display_funcs->p_get_pixel_formats = win32u_get_pixel_formats; + strcpy( wgl_extensions, driver_funcs->p_init_wgl_extensions() ); display_funcs->p_wglGetPixelFormat = win32u_wglGetPixelFormat; display_funcs->p_wglSetPixelFormat = win32u_wglSetPixelFormat; diff --git a/dlls/wineandroid.drv/opengl.c b/dlls/wineandroid.drv/opengl.c index c6c42a3bf2b..9b48b9d3ba0 100644 --- a/dlls/wineandroid.drv/opengl.c +++ b/dlls/wineandroid.drv/opengl.c @@ -244,11 +244,15 @@ static struct wgl_context *create_context( HDC hdc, struct wgl_context *share, c return ctx; }
-static void describe_pixel_format( struct egl_pixel_format *fmt, PIXELFORMATDESCRIPTOR *pfd ) +static BOOL android_describe_pixel_format( int format, struct wgl_pixel_format *desc ) { + struct egl_pixel_format *fmt = pixel_formats + format - 1; + PIXELFORMATDESCRIPTOR *pfd = &desc->pfd; EGLint val; EGLConfig config = fmt->config;
+ if (format <= 0 || format > nb_pixel_formats) return FALSE; + memset( pfd, 0, sizeof(*pfd) ); pfd->nSize = sizeof(*pfd); pfd->nVersion = 1; @@ -275,6 +279,7 @@ static void describe_pixel_format( struct egl_pixel_format *fmt, PIXELFORMATDESC pfd->cBlueShift = pfd->cAlphaShift + pfd->cAlphaBits; pfd->cGreenShift = pfd->cBlueShift + pfd->cBlueBits; pfd->cRedShift = pfd->cGreenShift + pfd->cGreenBits; + return TRUE; }
/*********************************************************************** @@ -505,24 +510,6 @@ static BOOL android_wglSwapBuffers( HDC hdc ) return TRUE; }
-/********************************************************************** - * android_get_pixel_formats - */ -static void android_get_pixel_formats( struct wgl_pixel_format *formats, - UINT max_formats, UINT *num_formats, - UINT *num_onscreen_formats ) -{ - UINT i; - - if (formats) - { - for (i = 0; i < min( max_formats, nb_pixel_formats ); ++i) - describe_pixel_format( &pixel_formats[i], &formats[i].pfd ); - } - *num_formats = nb_pixel_formats; - *num_onscreen_formats = nb_onscreen_formats; -} - static void wglFinish(void) { struct wgl_context *ctx = NtCurrentTeb()->glContext; @@ -863,8 +850,59 @@ static void init_opengl_funcs(void) #undef REDIRECT }
+static UINT android_init_pixel_formats( UINT *onscreen_count ) +{ + EGLConfig *configs; + EGLint count, i, pass; + + p_eglGetConfigs( display, NULL, 0, &count ); + configs = malloc( count * sizeof(*configs) ); + pixel_formats = malloc( count * sizeof(*pixel_formats) ); + p_eglGetConfigs( display, configs, count, &count ); + if (!count || !configs || !pixel_formats) + { + free( configs ); + free( pixel_formats ); + ERR( "eglGetConfigs returned no configs\n" ); + return 0; + } + + for (pass = 0; pass < 2; pass++) + { + for (i = 0; i < count; i++) + { + EGLint id, type, visual_id, native, render, color, r, g, b, d, s; + + p_eglGetConfigAttrib( display, configs[i], EGL_SURFACE_TYPE, &type ); + if (!(type & EGL_WINDOW_BIT) == !pass) continue; + p_eglGetConfigAttrib( display, configs[i], EGL_RENDERABLE_TYPE, &render ); + if (egl_client_version == 2 && !(render & EGL_OPENGL_ES2_BIT)) continue; + + pixel_formats[nb_pixel_formats++].config = configs[i]; + + p_eglGetConfigAttrib( display, configs[i], EGL_CONFIG_ID, &id ); + p_eglGetConfigAttrib( display, configs[i], EGL_NATIVE_VISUAL_ID, &visual_id ); + p_eglGetConfigAttrib( display, configs[i], EGL_NATIVE_RENDERABLE, &native ); + p_eglGetConfigAttrib( display, configs[i], EGL_COLOR_BUFFER_TYPE, &color ); + p_eglGetConfigAttrib( display, configs[i], EGL_RED_SIZE, &r ); + p_eglGetConfigAttrib( display, configs[i], EGL_GREEN_SIZE, &g ); + p_eglGetConfigAttrib( display, configs[i], EGL_BLUE_SIZE, &b ); + p_eglGetConfigAttrib( display, configs[i], EGL_DEPTH_SIZE, &d ); + p_eglGetConfigAttrib( display, configs[i], EGL_STENCIL_SIZE, &s ); + TRACE( "%u: config %u id %u type %x visual %u native %u render %x colortype %u rgb %u,%u,%u depth %u stencil %u\n", + nb_pixel_formats, i, id, type, visual_id, native, render, color, r, g, b, d, s ); + } + if (!pass) nb_onscreen_formats = nb_pixel_formats; + } + + *onscreen_count = nb_onscreen_formats; + return nb_pixel_formats; +} + static const struct opengl_driver_funcs android_driver_funcs = { + .p_init_pixel_formats = android_init_pixel_formats, + .p_describe_pixel_format = android_describe_pixel_format, .p_init_wgl_extensions = android_init_wgl_extensions, .p_set_pixel_format = android_set_pixel_format, }; @@ -874,8 +912,7 @@ static const struct opengl_driver_funcs android_driver_funcs = */ UINT ANDROID_OpenGLInit( UINT version, struct opengl_funcs **funcs, const struct opengl_driver_funcs **driver_funcs ) { - EGLConfig *configs; - EGLint major, minor, count, i, pass; + EGLint major, minor;
if (version != WINE_OPENGL_DRIVER_VERSION) { @@ -916,46 +953,6 @@ UINT ANDROID_OpenGLInit( UINT version, struct opengl_funcs **funcs, const struct if (!p_eglInitialize( display, &major, &minor )) return 0; TRACE( "display %p version %u.%u\n", display, major, minor );
- p_eglGetConfigs( display, NULL, 0, &count ); - configs = malloc( count * sizeof(*configs) ); - pixel_formats = malloc( count * sizeof(*pixel_formats) ); - p_eglGetConfigs( display, configs, count, &count ); - if (!count || !configs || !pixel_formats) - { - free( configs ); - free( pixel_formats ); - ERR( "eglGetConfigs returned no configs\n" ); - return 0; - } - - for (pass = 0; pass < 2; pass++) - { - for (i = 0; i < count; i++) - { - EGLint id, type, visual_id, native, render, color, r, g, b, d, s; - - p_eglGetConfigAttrib( display, configs[i], EGL_SURFACE_TYPE, &type ); - if (!(type & EGL_WINDOW_BIT) == !pass) continue; - p_eglGetConfigAttrib( display, configs[i], EGL_RENDERABLE_TYPE, &render ); - if (egl_client_version == 2 && !(render & EGL_OPENGL_ES2_BIT)) continue; - - pixel_formats[nb_pixel_formats++].config = configs[i]; - - p_eglGetConfigAttrib( display, configs[i], EGL_CONFIG_ID, &id ); - p_eglGetConfigAttrib( display, configs[i], EGL_NATIVE_VISUAL_ID, &visual_id ); - p_eglGetConfigAttrib( display, configs[i], EGL_NATIVE_RENDERABLE, &native ); - p_eglGetConfigAttrib( display, configs[i], EGL_COLOR_BUFFER_TYPE, &color ); - p_eglGetConfigAttrib( display, configs[i], EGL_RED_SIZE, &r ); - p_eglGetConfigAttrib( display, configs[i], EGL_GREEN_SIZE, &g ); - p_eglGetConfigAttrib( display, configs[i], EGL_BLUE_SIZE, &b ); - p_eglGetConfigAttrib( display, configs[i], EGL_DEPTH_SIZE, &d ); - p_eglGetConfigAttrib( display, configs[i], EGL_STENCIL_SIZE, &s ); - TRACE( "%u: config %u id %u type %x visual %u native %u render %x colortype %u rgb %u,%u,%u depth %u stencil %u\n", - nb_pixel_formats, i, id, type, visual_id, native, render, color, r, g, b, d, s ); - } - if (!pass) nb_onscreen_formats = nb_pixel_formats; - } - init_opengl_funcs(); *funcs = &egl_funcs; *driver_funcs = &android_driver_funcs; @@ -985,7 +982,6 @@ static struct opengl_funcs egl_funcs = .p_wglMakeCurrent = android_wglMakeCurrent, .p_wglShareLists = android_wglShareLists, .p_wglSwapBuffers = android_wglSwapBuffers, - .p_get_pixel_formats = android_get_pixel_formats, #define USE_GL_FUNC(name) .p_##name = (void *)glstub_##name, ALL_GL_FUNCS #undef USE_GL_FUNC diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 34315219d3c..f6b0ff90d7f 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -1106,9 +1106,8 @@ static CFComparisonResult pixel_format_comparator(const void *val1, const void * }
-static BOOL init_pixel_formats(void) +static UINT macdrv_init_pixel_formats(UINT *onscreen_count) { - BOOL ret = FALSE; CGLRendererInfoObj renderer_info; GLint rendererCount; CGLError err; @@ -1123,7 +1122,7 @@ static BOOL init_pixel_formats(void) if (err) { WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err)); - return FALSE; + return 0; }
pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); @@ -1131,7 +1130,7 @@ static BOOL init_pixel_formats(void) { WARN("CFSetCreateMutable failed\n"); CGLDestroyRendererInfo(renderer_info); - return FALSE; + return 0; }
pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -1140,7 +1139,7 @@ static BOOL init_pixel_formats(void) WARN("CFArrayCreateMutable failed\n"); CFRelease(pixel_format_set); CGLDestroyRendererInfo(renderer_info); - return FALSE; + return 0; }
for (i = 0; i < rendererCount; i++) @@ -1180,16 +1179,20 @@ static BOOL init_pixel_formats(void)
nb_formats = range.length; TRACE("Total number of unique pixel formats: %d\n", nb_formats); - ret = TRUE; } else + { WARN("failed to allocate pixel format list\n"); + nb_formats = 0; + } } else WARN("got no pixel formats\n");
CFRelease(pixel_format_array); - return ret; + + *onscreen_count = nb_displayable_formats; + return nb_formats; }
@@ -3462,9 +3465,6 @@ UINT macdrv_OpenGLInit(UINT version, struct opengl_funcs **funcs, const struct o if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions)) pglFlushRenderAPPLE = dlsym(opengl_handle, "glFlushRenderAPPLE");
- if (!init_pixel_formats()) - goto failed; - *funcs = &opengl_funcs; *driver_funcs = &macdrv_driver_funcs; return STATUS_SUCCESS; @@ -3499,10 +3499,13 @@ void sync_gl_view(struct macdrv_win_data* data, const struct window_rects *old_r }
-static void describe_pixel_format(const pixel_format *pf, struct wgl_pixel_format *descr) +static BOOL macdrv_describe_pixel_format(int format, struct wgl_pixel_format *descr) { + const pixel_format *pf = pixel_formats + format - 1; const struct color_mode *mode;
+ if (format <= 0 || format > nb_formats) return FALSE; + memset(descr, 0, sizeof(*descr)); descr->pfd.nSize = sizeof(*descr); descr->pfd.nVersion = 1; @@ -3582,6 +3585,8 @@ static void describe_pixel_format(const pixel_format *pf, struct wgl_pixel_forma descr->max_pbuffer_width = gl_info.max_viewport_dims[0]; descr->max_pbuffer_height = gl_info.max_viewport_dims[1]; descr->max_pbuffer_pixels = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1]; + + return TRUE; }
/*********************************************************************** @@ -3785,26 +3790,10 @@ static BOOL macdrv_wglSwapBuffers(HDC hdc) return TRUE; }
-/********************************************************************** - * macdrv_get_pixel_formats - */ -static void macdrv_get_pixel_formats(struct wgl_pixel_format *formats, - UINT max_formats, UINT *num_formats, - UINT *num_onscreen_formats) -{ - UINT i; - - if (formats) - { - for (i = 0; i < min(max_formats, nb_formats); ++i) - describe_pixel_format(&pixel_formats[i], &formats[i]); - } - *num_formats = nb_formats; - *num_onscreen_formats = nb_displayable_formats; -} - static const struct opengl_driver_funcs macdrv_driver_funcs = { + .p_init_pixel_formats = macdrv_init_pixel_formats, + .p_describe_pixel_format = macdrv_describe_pixel_format, .p_init_wgl_extensions = macdrv_init_wgl_extensions, .p_set_pixel_format = macdrv_set_pixel_format, }; @@ -3818,5 +3807,4 @@ static struct opengl_funcs opengl_funcs = .p_wglMakeCurrent = macdrv_wglMakeCurrent, .p_wglShareLists = macdrv_wglShareLists, .p_wglSwapBuffers = macdrv_wglSwapBuffers, - .p_get_pixel_formats = macdrv_get_pixel_formats, }; diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 849a2c3730b..9c4e7234d3d 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -992,13 +992,13 @@ static BOOL wayland_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const in return GL_TRUE; }
-static void describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt, BOOL pbuffer_single) +static BOOL describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt, BOOL pbuffer_single) { EGLint value, surface_type; PIXELFORMATDESCRIPTOR *pfd = &fmt->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; + if (!p_eglGetConfigAttrib(egl_display, config, EGL_SURFACE_TYPE, &surface_type)) return FALSE;
memset(fmt, 0, sizeof(*fmt)); pfd->nSize = sizeof(*pfd); @@ -1116,24 +1116,19 @@ static void describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt
#undef SET_ATTRIB #undef SET_ATTRIB_ARB + return TRUE; }
-static void wayland_get_pixel_formats(struct wgl_pixel_format *formats, - UINT max_formats, UINT *num_formats, - UINT *num_onscreen_formats) +static BOOL wayland_describe_pixel_format(int format, struct wgl_pixel_format *desc) { - UINT i; - - if (formats) - { - for (i = 0; i < min(max_formats, num_egl_configs); ++i) - describe_pixel_format(egl_configs[i], &formats[i], FALSE); - /* Add single-buffered pbuffer capable configs. */ - for (i = num_egl_configs; i < min(max_formats, 2 * num_egl_configs); ++i) - describe_pixel_format(egl_configs[i - num_egl_configs], &formats[i], TRUE); - } - *num_formats = 2 * num_egl_configs; - *num_onscreen_formats = num_egl_configs; + if (format <= 0) + return FALSE; + if (format <= num_egl_configs) + return describe_pixel_format(egl_configs[format - 1], desc, FALSE); + /* Add single-buffered pbuffer capable configs. */ + if (format <= 2 * num_egl_configs) + return describe_pixel_format(egl_configs[format - 1 - num_egl_configs], desc, TRUE); + return FALSE; }
static BOOL has_extension(const char *list, const char *ext) @@ -1211,7 +1206,7 @@ static const char *wayland_init_wgl_extensions(void) return wgl_extensions; }
-static BOOL init_egl_configs(void) +static UINT wayland_init_pixel_formats(UINT *onscreen_count) { EGLint i; const EGLint attribs[] = @@ -1225,7 +1220,7 @@ static BOOL init_egl_configs(void) if (!(egl_configs = malloc(num_egl_configs * sizeof(*egl_configs)))) { ERR("Failed to allocate memory for EGL configs\n"); - return FALSE; + return 0; } if (!p_eglChooseConfig(egl_display, attribs, egl_configs, num_egl_configs, &num_egl_configs) || @@ -1235,7 +1230,7 @@ static BOOL init_egl_configs(void) egl_configs = NULL; num_egl_configs = 0; ERR("Failed to get any configs from eglChooseConfig\n"); - return FALSE; + return 0; }
if (TRACE_ON(waylanddrv)) @@ -1262,11 +1257,14 @@ static BOOL init_egl_configs(void) } }
- return TRUE; + *onscreen_count = num_egl_configs; + return 2 * num_egl_configs; }
static const struct opengl_driver_funcs wayland_driver_funcs = { + .p_init_pixel_formats = wayland_init_pixel_formats, + .p_describe_pixel_format = wayland_describe_pixel_format, .p_init_wgl_extensions = wayland_init_wgl_extensions, .p_set_pixel_format = wayland_set_pixel_format, }; @@ -1364,7 +1362,6 @@ UINT WAYLAND_OpenGLInit(UINT version, struct opengl_funcs **funcs, const struct 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; *funcs = &opengl_funcs; *driver_funcs = &wayland_driver_funcs; return STATUS_SUCCESS; @@ -1384,7 +1381,6 @@ static struct opengl_funcs opengl_funcs = .p_wglMakeCurrent = wayland_wglMakeCurrent, .p_wglShareLists = wayland_wglShareLists, .p_wglSwapBuffers = wayland_wglSwapBuffers, - .p_get_pixel_formats = wayland_get_pixel_formats, };
/********************************************************************** diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index a4c41e1289b..239511b1679 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -280,7 +280,6 @@ static const BOOL is_win64 = sizeof(void *) > sizeof(int);
static struct opengl_funcs opengl_funcs;
-static void init_pixel_formats( Display *display ); static BOOL glxRequireVersion(int requiredVersion);
static void dump_PIXELFORMATDESCRIPTOR(const PIXELFORMATDESCRIPTOR *ppfd) { @@ -713,8 +712,6 @@ UINT X11DRV_OpenGLInit( UINT version, struct opengl_funcs **funcs, const struct pglXSwapBuffersMscOML = pglXGetProcAddressARB( (const GLubyte *)"glXSwapBuffersMscOML" ); }
- init_pixel_formats( gdi_display ); - *funcs = &opengl_funcs; *driver_funcs = &x11drv_driver_funcs; return STATUS_SUCCESS; @@ -773,7 +770,7 @@ static BOOL check_fbconfig_bitmap_capability(Display *display, GLXFBConfig fbcon return !dbuf && (value & GLX_PIXMAP_BIT); }
-static void init_pixel_formats( Display *display ) +static UINT x11drv_init_pixel_formats( UINT *onscreen_count ) { struct glx_pixel_format *list; int size = 0, onscreen_size = 0; @@ -781,11 +778,11 @@ static void init_pixel_formats( Display *display ) GLXFBConfig* cfgs; XVisualInfo *visinfo;
- cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs); + cfgs = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs); if (NULL == cfgs || 0 == nCfgs) { if(cfgs != NULL) XFree(cfgs); ERR("glXChooseFBConfig returns NULL\n"); - return; + return 0; }
/* Bitmap rendering on Windows implies the use of the Microsoft GDI software renderer. @@ -797,7 +794,7 @@ static void init_pixel_formats( Display *display ) */ for(i=0, bmp_formats=0; i<nCfgs; i++) { - if(check_fbconfig_bitmap_capability(display, cfgs[i])) + if(check_fbconfig_bitmap_capability(gdi_display, cfgs[i])) bmp_formats++; } TRACE("Found %d bitmap capable fbconfigs\n", bmp_formats); @@ -809,8 +806,8 @@ static void init_pixel_formats( Display *display ) for(run=0; run < 2; run++) { for(i=0; i<nCfgs; i++) { - pglXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &fmt_id); - visinfo = pglXGetVisualFromFBConfig(display, cfgs[i]); + pglXGetFBConfigAttrib(gdi_display, cfgs[i], GLX_FBCONFIG_ID, &fmt_id); + visinfo = pglXGetVisualFromFBConfig(gdi_display, cfgs[i]);
/* The first run we only add onscreen formats (ones which have an associated X Visual). * The second run we only set offscreen formats. */ @@ -833,19 +830,19 @@ static void init_pixel_formats( Display *display ) list[size].fbconfig = cfgs[i]; list[size].visual = visinfo; list[size].fmt_id = fmt_id; - list[size].render_type = get_render_type_from_fbconfig(display, cfgs[i]); + list[size].render_type = get_render_type_from_fbconfig(gdi_display, cfgs[i]); list[size].dwFlags = 0; size++; onscreen_size++;
/* Clone a format if it is bitmap capable for indirect rendering to bitmaps */ - if(check_fbconfig_bitmap_capability(display, cfgs[i])) + if(check_fbconfig_bitmap_capability(gdi_display, cfgs[i])) { TRACE("Found bitmap capable format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", fmt_id, size+1, i); list[size].fbconfig = cfgs[i]; list[size].visual = visinfo; list[size].fmt_id = fmt_id; - list[size].render_type = get_render_type_from_fbconfig(display, cfgs[i]); + list[size].render_type = get_render_type_from_fbconfig(gdi_display, cfgs[i]); list[size].dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_GENERIC_FORMAT; size++; onscreen_size++; @@ -869,7 +866,7 @@ static void init_pixel_formats( Display *display ) TRACE("Found offscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", fmt_id, size+1, i); list[size].fbconfig = cfgs[i]; list[size].fmt_id = fmt_id; - list[size].render_type = get_render_type_from_fbconfig(display, cfgs[i]); + list[size].render_type = get_render_type_from_fbconfig(gdi_display, cfgs[i]); list[size].dwFlags = 0; size++; } @@ -882,6 +879,9 @@ static void init_pixel_formats( Display *display ) pixel_formats = list; nb_pixel_formats = size; nb_onscreen_formats = onscreen_size; + + *onscreen_count = onscreen_size; + return size; }
static inline BOOL is_valid_pixel_format( int format ) @@ -1337,12 +1337,7 @@ void destroy_gl_drawable( HWND hwnd ) }
-/** - * describe_pixel_format - * - * Get the wgl_pixel_format description for the given id - */ -static int describe_pixel_format( int iPixelFormat, struct wgl_pixel_format *pf ) +static BOOL x11drv_describe_pixel_format( int iPixelFormat, struct wgl_pixel_format *pf ) { int value, drawable_type = 0, render_type = 0; int rb, gb, bb, ab; @@ -1355,7 +1350,7 @@ static int describe_pixel_format( int iPixelFormat, struct wgl_pixel_format *pf if (!fmt) { WARN( "unexpected format %d\n", iPixelFormat ); - return 0; + return FALSE; }
/* If we can't get basic information, there is no point continuing */ @@ -1536,7 +1531,7 @@ static int describe_pixel_format( int iPixelFormat, struct wgl_pixel_format *pf
if (TRACE_ON(wgl)) dump_PIXELFORMATDESCRIPTOR( &pf->pfd );
- return nb_onscreen_formats; + return TRUE; }
/*********************************************************************** @@ -2677,23 +2672,10 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) return TRUE; }
-static void glxdrv_get_pixel_formats( struct wgl_pixel_format *formats, - UINT max_formats, UINT *num_formats, - UINT *num_onscreen_formats ) -{ - UINT i; - - if (formats) - { - for (i = 0; i < min( max_formats, nb_pixel_formats ); ++i) - describe_pixel_format( i + 1, &formats[i] ); - } - *num_formats = nb_pixel_formats; - *num_onscreen_formats = nb_onscreen_formats; -} - static const struct opengl_driver_funcs x11drv_driver_funcs = { + .p_init_pixel_formats = x11drv_init_pixel_formats, + .p_describe_pixel_format = x11drv_describe_pixel_format, .p_init_wgl_extensions = x11drv_init_wgl_extensions, .p_set_pixel_format = x11drv_set_pixel_format, }; @@ -2707,7 +2689,6 @@ static struct opengl_funcs opengl_funcs = .p_wglMakeCurrent = glxdrv_wglMakeCurrent, .p_wglShareLists = glxdrv_wglShareLists, .p_wglSwapBuffers = glxdrv_wglSwapBuffers, - .p_get_pixel_formats = glxdrv_get_pixel_formats, };
#else /* no OpenGL includes */ diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index c18edb5476b..f652a58c920 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -113,6 +113,8 @@ struct opengl_funcs /* interface between win32u and the user drivers */ struct opengl_driver_funcs { + UINT (*p_init_pixel_formats)(UINT*); + BOOL (*p_describe_pixel_format)(int,struct wgl_pixel_format*); const char *(*p_init_wgl_extensions)(void); BOOL (*p_set_pixel_format)(HWND,int,int,BOOL); };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/tests/opengl.c | 256 +++++++++++++++++++++++------------ 1 file changed, 170 insertions(+), 86 deletions(-)
diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 387673481e0..1badada30e5 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -44,7 +44,6 @@ static HGLRC (WINAPI *pwglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext,
/* WGL_ARB_extensions_string */ static const char* (WINAPI *pwglGetExtensionsStringARB)(HDC); -static int (WINAPI *pwglReleasePbufferDCARB)(HPBUFFERARB, HDC);
/* WGL_ARB_make_current_read */ static BOOL (WINAPI *pwglMakeContextCurrentARB)(HDC hdraw, HDC hread, HGLRC hglrc); @@ -56,7 +55,15 @@ static BOOL (WINAPI *pwglGetPixelFormatAttribivARB)(HDC, int, int, UINT, const i
/* WGL_ARB_pbuffer */ static HPBUFFERARB (WINAPI *pwglCreatePbufferARB)(HDC, int, int, int, const int *); +static BOOL (WINAPI *pwglDestroyPbufferARB)(HPBUFFERARB); static HDC (WINAPI *pwglGetPbufferDCARB)(HPBUFFERARB); +static int (WINAPI *pwglReleasePbufferDCARB)(HPBUFFERARB, HDC); +static BOOL (WINAPI *pwglQueryPbufferARB)(HPBUFFERARB,int,int*); + +/* WGL_ARB_render_texture */ +static BOOL (WINAPI *pwglBindTexImageARB)(HPBUFFERARB,int); +static BOOL (WINAPI *pwglReleaseTexImageARB)(HPBUFFERARB,int); +static BOOL (WINAPI *pwglSetPbufferAttribARB)(HPBUFFERARB,const int*);
/* WGL_EXT_swap_control */ static BOOL (WINAPI *pwglSwapIntervalEXT)(int interval); @@ -113,8 +120,15 @@ static void init_functions(void)
/* WGL_ARB_pbuffer */ GET_PROC(wglCreatePbufferARB) + GET_PROC(wglDestroyPbufferARB) GET_PROC(wglGetPbufferDCARB) GET_PROC(wglReleasePbufferDCARB) + GET_PROC(wglQueryPbufferARB) + + /* WGL_ARB_render_texture */ + GET_PROC(wglBindTexImageARB) + GET_PROC(wglReleaseTexImageARB) + GET_PROC(wglSetPbufferAttribARB)
/* WGL_EXT_swap_control */ GET_PROC(wglSwapIntervalEXT) @@ -159,104 +173,174 @@ static BOOL gl_extension_supported(const char *extensions, const char *extension return FALSE; }
-static void test_pbuffers(HDC hdc) +static void test_pbuffers( HDC hdc ) { - const int iAttribList[] = { WGL_DRAW_TO_PBUFFER_ARB, 1, /* Request pbuffer support */ - 0 }; - int iFormats[MAX_FORMATS]; - unsigned int nOnscreenFormats; - unsigned int nFormats; - int i, res; - int iPixelFormat = 0; - - nOnscreenFormats = DescribePixelFormat(hdc, 0, 0, NULL); + const int attribs[] = { WGL_DRAW_TO_PBUFFER_ARB, 1, 0 }; + int formats[MAX_FORMATS], pbuffer_attribs[3] = {0}; + unsigned int i, count, onscreen; + HDC pbuffer_dc, tmp_dc; + HPBUFFERARB pbuffer; + int res, value; + BOOL ret;
- /* When you want to render to a pbuffer you need to call wglGetPbufferDCARB which - * returns a 'magic' HDC which you can then pass to wglMakeCurrent to switch rendering - * to the pbuffer. Below some tests are performed on what happens if you use standard WGL calls - * on this 'magic' HDC for both a pixelformat that support onscreen and offscreen rendering - * and a pixelformat that's only available for offscreen rendering (this means that only - * wglChoosePixelFormatARB and friends know about the format. - * - * The first thing we need are pixelformats with pbuffer capabilities. - */ - res = pwglChoosePixelFormatARB(hdc, iAttribList, NULL, MAX_FORMATS, iFormats, &nFormats); - if(res <= 0) + onscreen = DescribePixelFormat( hdc, 0, 0, NULL ); + if ((res = pwglChoosePixelFormatARB( hdc, attribs, NULL, MAX_FORMATS, formats, &count )) <= 0) { - skip("No pbuffer compatible formats found while WGL_ARB_pbuffer is supported\n"); + win_skip( "No pixel format with WGL_DRAW_TO_PBUFFER_ARB, skipping tests\n" ); return; } - trace("nOnscreenFormats: %d\n", nOnscreenFormats); - trace("Total number of pbuffer capable pixelformats: %d\n", nFormats);
- /* Try to select an onscreen pixelformat out of the list */ - for(i=0; i < nFormats; i++) + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( NULL, formats[0], 100, 100, pbuffer_attribs ); + todo_wine ok( !!pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_HANDLE, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, 0, 100, 100, pbuffer_attribs ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_GEN_FAILURE, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 0, 100, pbuffer_attribs ); + todo_wine ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + if (!winetest_platform_is_wine) { - /* Check if the format is onscreen, if it is choose it */ - if(iFormats[i] <= nOnscreenFormats) - { - iPixelFormat = iFormats[i]; - trace("Selected iPixelFormat=%d\n", iPixelFormat); - break; - } - } - - /* A video driver supports a large number of onscreen and offscreen pixelformats. - * The traditional WGL calls only see a subset of the whole pixelformat list. First - * of all they only see the onscreen formats (the offscreen formats are at the end of the - * pixelformat list) and second extended pixelformat capabilities are hidden from the - * standard WGL calls. Only functions that depend on WGL_ARB_pixel_format can see them. - * - * Below we check if the pixelformat is also supported onscreen. - */ - if(iPixelFormat != 0) - { - HDC pbuffer_hdc; - int attrib = 0; - HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, &attrib); - if(!pbuffer) - skip("Pbuffer creation failed!\n"); - - /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */ - pbuffer_hdc = pwglGetPbufferDCARB(pbuffer); - res = GetPixelFormat(pbuffer_hdc); - ok(res == iPixelFormat, "Unexpected iPixelFormat=%d returned by GetPixelFormat for format %d\n", res, iPixelFormat); - trace("iPixelFormat returned by GetPixelFormat: %d\n", res); - trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat); - - pwglReleasePbufferDCARB(pbuffer, pbuffer_hdc); + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, formats[0], -1, 100, pbuffer_attribs ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); } - else skip("Pbuffer test for onscreen pixelformat skipped as no onscreen format with pbuffer capabilities have been found\n"); - - /* Search for a real offscreen format */ - for(i=0, iPixelFormat=0; i<nFormats; i++) + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 100, 0, pbuffer_attribs ); + todo_wine ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + if (!winetest_platform_is_wine) { - if(iFormats[i] > nOnscreenFormats) - { - iPixelFormat = iFormats[i]; - trace("Selected iPixelFormat: %d\n", iPixelFormat); - break; - } + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 100, -1, pbuffer_attribs ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + } + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 100, 100, NULL ); + ok( !!pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_HANDLE, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + + for (i = 0; i < count; i++) + { + winetest_push_context( "%u", formats[i] ); + pbuffer = pwglCreatePbufferARB( hdc, formats[i], 640, 480, pbuffer_attribs ); + ok( !!pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + pbuffer_dc = pwglGetPbufferDCARB( pbuffer ); + ok( pbuffer_dc != hdc, "got %p\n", pbuffer_dc ); + res = GetPixelFormat( pbuffer_dc ); + if (formats[i] > onscreen) ok( res == 1, "got format %d\n", res ); + else ok( res == formats[i] || broken( res == 1 ), "got format %d\n", res ); + ret = pwglDestroyPbufferARB( pbuffer ); + ok( ret == 1, "got %u\n", ret ); + winetest_pop_context(); }
- if(iPixelFormat != 0) + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 640, 480, pbuffer_attribs ); + ok( !!pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + + pbuffer_dc = pwglGetPbufferDCARB( pbuffer ); + ok( pbuffer_dc != hdc, "got %p\n", pbuffer_dc ); + + /* wglGetPbufferDCARB returns the same DC every time */ + tmp_dc = pwglGetPbufferDCARB( pbuffer ); + todo_wine ok( tmp_dc == pbuffer_dc, "got %p\n", tmp_dc ); + + /* releasing the wrong DC has no effect */ + SetLastError( 0xdeadbeef ); + ret = pwglReleasePbufferDCARB( pbuffer, hdc ); + todo_wine ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = pwglReleasePbufferDCARB( pbuffer, pbuffer_dc ); + ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglReleasePbufferDCARB( pbuffer, pbuffer_dc ); + todo_wine ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + /* releasing the DC more than it was acquired has no effect */ + SetLastError( 0xdeadbeef ); + ret = pwglReleasePbufferDCARB( pbuffer, pbuffer_dc ); + todo_wine ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( NULL, WGL_PBUFFER_WIDTH_ARB, &value ); + ok( ret == 0, "got %u\n", ret ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_HANDLE, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, 0, &value ); + todo_wine ok( ret == 0, "got %u\n", ret ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, 0xdeadbeef, &value ); + todo_wine ok( ret == 0, "got %u\n", ret ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, WGL_PBUFFER_WIDTH_ARB, &value ); + ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, WGL_PBUFFER_HEIGHT_ARB, &value ); + ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, WGL_PBUFFER_LOST_ARB, &value ); + ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, WGL_TEXTURE_FORMAT_ARB, &value ); + todo_wine ok( ret == 0, "got %u\n", ret ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, WGL_TEXTURE_TARGET_ARB, &value ); + todo_wine ok( ret == 0, "got %u\n", ret ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pwglQueryPbufferARB( pbuffer, WGL_MIPMAP_TEXTURE_ARB, &value ); + todo_wine ok( ret == 0, "got %u\n", ret ); + todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = pwglDestroyPbufferARB( pbuffer ); + ok( ret == 1, "got %u\n", ret ); + ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); + /* destroying the pbuffer multiple times */ + SetLastError( 0xdeadbeef ); + ret = pwglDestroyPbufferARB( pbuffer ); + ok( ret == 0, "got %u\n", ret ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_HANDLE, "got %#lx\n", GetLastError() ); + + if (!winetest_platform_is_wine) { - HDC pbuffer_hdc; - HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, NULL); - if(pbuffer) - { - /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */ - pbuffer_hdc = pwglGetPbufferDCARB(pbuffer); - res = GetPixelFormat(pbuffer_hdc); - - ok(res == 1, "Unexpected iPixelFormat=%d (1 expected) returned by GetPixelFormat for offscreen format %d\n", res, iPixelFormat); - trace("iPixelFormat returned by GetPixelFormat: %d\n", res); - trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat); - pwglReleasePbufferDCARB(pbuffer, hdc); - } - else skip("Pbuffer creation failed!\n"); + pbuffer_attribs[0] = WGL_PBUFFER_LARGEST_ARB; + pbuffer_attribs[1] = 1; + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 65535, 65535, pbuffer_attribs ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); + + pbuffer_attribs[0] = WGL_PBUFFER_LARGEST_ARB; + pbuffer_attribs[1] = 0; + SetLastError( 0xdeadbeef ); + pbuffer = pwglCreatePbufferARB( hdc, formats[0], 65535, 65535, pbuffer_attribs ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + ok( (GetLastError() & 0xffff) == ERROR_GEN_FAILURE, "got %#lx\n", GetLastError() ); + if (pbuffer) pwglDestroyPbufferARB( pbuffer ); } - else skip("Pbuffer test for offscreen pixelformat skipped as no offscreen-only format with pbuffer capabilities has been found\n"); }
static int test_pfd(const PIXELFORMATDESCRIPTOR *pfd, PIXELFORMATDESCRIPTOR *fmt)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/tests/opengl.c | 22 +- dlls/win32u/opengl.c | 323 +++++++++++++++++++++++++ dlls/winex11.drv/opengl.c | 445 +++-------------------------------- include/wine/opengl_driver.h | 3 + 4 files changed, 368 insertions(+), 425 deletions(-)
diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 1badada30e5..bf376dadbbc 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -202,30 +202,24 @@ static void test_pbuffers( HDC hdc ) if (pbuffer) pwglDestroyPbufferARB( pbuffer ); SetLastError( 0xdeadbeef ); pbuffer = pwglCreatePbufferARB( hdc, formats[0], 0, 100, pbuffer_attribs ); - todo_wine ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); - todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); if (pbuffer) pwglDestroyPbufferARB( pbuffer ); - if (!winetest_platform_is_wine) - { SetLastError( 0xdeadbeef ); pbuffer = pwglCreatePbufferARB( hdc, formats[0], -1, 100, pbuffer_attribs ); ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); if (pbuffer) pwglDestroyPbufferARB( pbuffer ); - } SetLastError( 0xdeadbeef ); pbuffer = pwglCreatePbufferARB( hdc, formats[0], 100, 0, pbuffer_attribs ); - todo_wine ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); - todo_wine ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); + ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); + ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); if (pbuffer) pwglDestroyPbufferARB( pbuffer ); - if (!winetest_platform_is_wine) - { SetLastError( 0xdeadbeef ); pbuffer = pwglCreatePbufferARB( hdc, formats[0], 100, -1, pbuffer_attribs ); ok( !pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); ok( (GetLastError() & 0xffff) == ERROR_INVALID_DATA, "got %#lx\n", GetLastError() ); if (pbuffer) pwglDestroyPbufferARB( pbuffer ); - } SetLastError( 0xdeadbeef ); pbuffer = pwglCreatePbufferARB( hdc, formats[0], 100, 100, NULL ); ok( !!pbuffer, "wglCreatePbufferARB returned %p\n", pbuffer ); @@ -255,12 +249,12 @@ static void test_pbuffers( HDC hdc )
/* wglGetPbufferDCARB returns the same DC every time */ tmp_dc = pwglGetPbufferDCARB( pbuffer ); - todo_wine ok( tmp_dc == pbuffer_dc, "got %p\n", tmp_dc ); + ok( tmp_dc == pbuffer_dc, "got %p\n", tmp_dc );
/* releasing the wrong DC has no effect */ SetLastError( 0xdeadbeef ); ret = pwglReleasePbufferDCARB( pbuffer, hdc ); - todo_wine ok( ret == 1, "got %u\n", ret ); + ok( ret == 1, "got %u\n", ret ); ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() );
SetLastError( 0xdeadbeef ); @@ -269,12 +263,12 @@ static void test_pbuffers( HDC hdc ) ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); SetLastError( 0xdeadbeef ); ret = pwglReleasePbufferDCARB( pbuffer, pbuffer_dc ); - todo_wine ok( ret == 1, "got %u\n", ret ); + ok( ret == 1, "got %u\n", ret ); ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() ); /* releasing the DC more than it was acquired has no effect */ SetLastError( 0xdeadbeef ); ret = pwglReleasePbufferDCARB( pbuffer, pbuffer_dc ); - todo_wine ok( ret == 1, "got %u\n", ret ); + ok( ret == 1, "got %u\n", ret ); ok( GetLastError() == 0xdeadbeef, "got %#lx\n", GetLastError() );
SetLastError( 0xdeadbeef ); diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 9686f64ab2b..00b74b0311e 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -39,6 +39,26 @@
WINE_DEFAULT_DEBUG_CHANNEL(wgl);
+struct wgl_pbuffer +{ + const struct opengl_driver_funcs *driver_funcs; + struct opengl_funcs *funcs; + void *driver_private; + + HDC hdc; + GLsizei width; + GLsizei height; + GLenum texture_format; + GLenum texture_target; + + struct wgl_context *tmp_context; + struct wgl_context *prev_context; + struct list entry; +}; + +static pthread_mutex_t pbuffer_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct list pbuffer_list = LIST_INIT( pbuffer_list ); + static struct opengl_funcs *get_dc_funcs( HDC hdc, void *null_funcs );
static const struct @@ -502,6 +522,294 @@ static void win32u_get_pixel_formats( struct wgl_pixel_format *formats, UINT max *num_onscreen_formats = onscreen_count; }
+static struct wgl_pbuffer *win32u_wglCreatePbufferARB( HDC hdc, int format, int width, int height, + const int *attribs ) +{ + struct wgl_pbuffer *pbuffer; + struct opengl_funcs *funcs; + UINT total, onscreen; + BOOL largest = FALSE; + + TRACE( "(%p, %d, %d, %d, %p)\n", hdc, format, width, height, attribs ); + + if (!(funcs = get_dc_funcs( hdc, NULL ))) return FALSE; + funcs->p_get_pixel_formats( NULL, 0, &total, &onscreen ); + if (format <= 0 || format > total) + { + RtlSetLastWin32Error( ERROR_INVALID_PIXEL_FORMAT ); + return NULL; + } + if (width <= 0 || height <= 0) + { + RtlSetLastWin32Error( ERROR_INVALID_DATA ); + return NULL; + } + + if (!(pbuffer = calloc( 1, sizeof(*pbuffer) )) || !(pbuffer->hdc = NtGdiOpenDCW( NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL ))) + { + RtlSetLastWin32Error( ERROR_NO_SYSTEM_RESOURCES ); + free( pbuffer ); + return NULL; + } + NtGdiSetPixelFormat( pbuffer->hdc, format ); + pbuffer->driver_funcs = driver_funcs; + pbuffer->funcs = funcs; + pbuffer->width = width; + pbuffer->height = height; + + for (; attribs && attribs[0]; attribs += 2) + { + switch (attribs[0]) + { + case WGL_PBUFFER_LARGEST_ARB: + TRACE( "WGL_PBUFFER_LARGEST_ARB %#x\n", attribs[1] ); + largest = !!attribs[1]; + break; + + case WGL_TEXTURE_FORMAT_ARB: + TRACE( "WGL_TEXTURE_FORMAT_ARB %#x\n", attribs[1] ); + switch (attribs[1]) + { + case WGL_NO_TEXTURE_ARB: + pbuffer->texture_format = 0; + break; + case WGL_TEXTURE_RGB_ARB: + pbuffer->texture_format = GL_RGB; + break; + case WGL_TEXTURE_RGBA_ARB: + pbuffer->texture_format = GL_RGBA; + break; + /* WGL_FLOAT_COMPONENTS_NV */ + case WGL_TEXTURE_FLOAT_R_NV: + pbuffer->texture_format = GL_FLOAT_R_NV; + break; + case WGL_TEXTURE_FLOAT_RG_NV: + pbuffer->texture_format = GL_FLOAT_RG_NV; + break; + case WGL_TEXTURE_FLOAT_RGB_NV: + pbuffer->texture_format = GL_FLOAT_RGB_NV; + break; + case WGL_TEXTURE_FLOAT_RGBA_NV: + pbuffer->texture_format = GL_FLOAT_RGBA_NV; + break; + default: + FIXME( "Unknown texture format: %x\n", attribs[1] ); + goto failed; + } + break; + + case WGL_TEXTURE_TARGET_ARB: + TRACE( "WGL_TEXTURE_TARGET_ARB %#x\n", attribs[1] ); + switch (attribs[1]) + { + case WGL_NO_TEXTURE_ARB: + pbuffer->texture_target = 0; + break; + case WGL_TEXTURE_CUBE_MAP_ARB: + if (width != height) goto failed; + pbuffer->texture_target = GL_TEXTURE_CUBE_MAP; + break; + case WGL_TEXTURE_1D_ARB: + if (height != 1) goto failed; + pbuffer->texture_target = GL_TEXTURE_1D; + break; + case WGL_TEXTURE_2D_ARB: + pbuffer->texture_target = GL_TEXTURE_2D; + break; + case WGL_TEXTURE_RECTANGLE_NV: + pbuffer->texture_target = GL_TEXTURE_RECTANGLE_NV; + break; + default: + FIXME( "Unknown texture target: %x\n", attribs[1] ); + goto failed; + } + break; + + case WGL_MIPMAP_TEXTURE_ARB: + TRACE( "WGL_MIPMAP_TEXTURE_ARB %#x\n", attribs[1] ); + break; + + default: + WARN( "attribute %#x %#x not handled\n", attribs[0], attribs[1] ); + break; + } + } + + if (pbuffer->driver_funcs->p_pbuffer_create( pbuffer->hdc, format, largest, &pbuffer->width, + &pbuffer->height, &pbuffer->driver_private )) + { + pthread_mutex_lock( &pbuffer_mutex ); + list_add_tail( &pbuffer_list, &pbuffer->entry ); + pthread_mutex_unlock( &pbuffer_mutex ); + return pbuffer; + } + +failed: + RtlSetLastWin32Error( ERROR_INVALID_DATA ); + NtGdiDeleteObjectApp( pbuffer->hdc ); + free( pbuffer ); + return NULL; +} + +static BOOL win32u_wglDestroyPbufferARB( struct wgl_pbuffer *pbuffer ) +{ + TRACE( "pbuffer %p\n", pbuffer ); + + pthread_mutex_lock( &pbuffer_mutex ); + list_remove( &pbuffer->entry ); + pthread_mutex_unlock( &pbuffer_mutex ); + + pbuffer->driver_funcs->p_pbuffer_destroy( pbuffer->hdc, pbuffer->driver_private ); + if (pbuffer->tmp_context) pbuffer->funcs->p_wglDeleteContext( pbuffer->tmp_context ); + NtGdiDeleteObjectApp( pbuffer->hdc ); + free( pbuffer ); + + return GL_TRUE; +} + +static HDC win32u_wglGetPbufferDCARB( struct wgl_pbuffer *pbuffer ) +{ + TRACE( "pbuffer %p\n", pbuffer ); + return pbuffer->hdc; +} + +static int win32u_wglReleasePbufferDCARB( struct wgl_pbuffer *pbuffer, HDC hdc ) +{ + TRACE( "pbuffer %p, hdc %p\n", pbuffer, hdc ); + return TRUE; +} + +static BOOL win32u_wglQueryPbufferARB( struct wgl_pbuffer *pbuffer, int attrib, int *value ) +{ + TRACE( "pbuffer %p, attrib %#x, value %p\n", pbuffer, attrib, value ); + + switch (attrib) + { + case WGL_PBUFFER_WIDTH_ARB: + *value = pbuffer->width; + break; + case WGL_PBUFFER_HEIGHT_ARB: + *value = pbuffer->height; + break; + case WGL_PBUFFER_LOST_ARB: + *value = GL_FALSE; + break; + + case WGL_TEXTURE_FORMAT_ARB: + switch (pbuffer->texture_format) + { + case 0: *value = WGL_NO_TEXTURE_ARB; break; + case GL_RGB: *value = WGL_TEXTURE_RGB_ARB; break; + case GL_RGBA: *value = WGL_TEXTURE_RGBA_ARB; break; + /* WGL_FLOAT_COMPONENTS_NV */ + case GL_FLOAT_R_NV: *value = WGL_TEXTURE_FLOAT_R_NV; break; + case GL_FLOAT_RG_NV: *value = WGL_TEXTURE_FLOAT_RG_NV; break; + case GL_FLOAT_RGB_NV: *value = WGL_TEXTURE_FLOAT_RGB_NV; break; + case GL_FLOAT_RGBA_NV: *value = WGL_TEXTURE_FLOAT_RGBA_NV; break; + default: ERR( "Unknown texture format: %x\n", pbuffer->texture_format ); + } + break; + + case WGL_TEXTURE_TARGET_ARB: + switch (pbuffer->texture_target) + { + case 0: *value = WGL_NO_TEXTURE_ARB; break; + case GL_TEXTURE_1D: *value = WGL_TEXTURE_1D_ARB; break; + case GL_TEXTURE_2D: *value = WGL_TEXTURE_2D_ARB; break; + case GL_TEXTURE_CUBE_MAP: *value = WGL_TEXTURE_CUBE_MAP_ARB; break; + case GL_TEXTURE_RECTANGLE_NV: *value = WGL_TEXTURE_RECTANGLE_NV; break; + } + break; + + case WGL_MIPMAP_TEXTURE_ARB: + *value = GL_FALSE; + FIXME( "WGL_MIPMAP_TEXTURE_ARB not supported\n" ); + break; + + default: + FIXME( "unexpected attribute %x\n", attrib ); + break; + } + + return GL_TRUE; +} + +static GLenum binding_from_target( GLenum target ) +{ + switch (target) + { + case GL_TEXTURE_CUBE_MAP: return GL_TEXTURE_BINDING_CUBE_MAP; + case GL_TEXTURE_1D: return GL_TEXTURE_BINDING_1D; + case GL_TEXTURE_2D: return GL_TEXTURE_BINDING_2D; + case GL_TEXTURE_RECTANGLE_NV: return GL_TEXTURE_BINDING_RECTANGLE_NV; + } + FIXME( "Unsupported target %#x\n", target ); + return 0; +} + +static BOOL win32u_wglBindTexImageARB( struct wgl_pbuffer *pbuffer, int buffer ) +{ + HDC prev_draw = NtCurrentTeb()->glReserved1[0], prev_read = NtCurrentTeb()->glReserved1[1]; + struct wgl_context *prev_context = NtCurrentTeb()->glContext; + int prev_texture = 0; + + TRACE( "pbuffer %p, buffer %d\n", pbuffer, buffer ); + + if (!pbuffer->texture_format) + { + RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); + return GL_FALSE; + } + + if (!pbuffer->tmp_context || pbuffer->prev_context != prev_context) + { + pthread_mutex_lock( &pbuffer_mutex ); + if (pbuffer->tmp_context) pbuffer->funcs->p_wglDeleteContext( pbuffer->tmp_context ); + pbuffer->tmp_context = pbuffer->funcs->p_wglCreateContextAttribsARB( pbuffer->hdc, prev_context, NULL ); + pbuffer->prev_context = prev_context; + pthread_mutex_unlock( &pbuffer_mutex ); + } + + pbuffer->funcs->p_glGetIntegerv( binding_from_target( pbuffer->texture_target ), &prev_texture ); + + /* Switch to our pbuffer */ + pbuffer->funcs->p_wglMakeCurrent( pbuffer->hdc, pbuffer->tmp_context ); + + /* Make sure that the prev_texture is set as the current texture state isn't shared + * between contexts. After that copy the pbuffer texture data. */ + pbuffer->funcs->p_glBindTexture( pbuffer->texture_target, prev_texture ); + pbuffer->funcs->p_glCopyTexImage2D( pbuffer->texture_target, 0, pbuffer->texture_format, 0, 0, + pbuffer->width, pbuffer->height, 0 ); + + /* Switch back to the original drawable and context */ + pbuffer->funcs->p_wglMakeContextCurrentARB( prev_draw, prev_read, prev_context ); + return GL_TRUE; +} + +static BOOL win32u_wglReleaseTexImageARB( struct wgl_pbuffer *pbuffer, int buffer ) +{ + TRACE( "pbuffer %p, buffer %d\n", pbuffer, buffer ); + + if (!pbuffer->texture_format) + { + RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); + return GL_FALSE; + } + return GL_TRUE; +} + +static BOOL win32u_wglSetPbufferAttribARB( struct wgl_pbuffer *pbuffer, const int *attribs ) +{ + TRACE( "pbuffer %p, attribs %p\n", pbuffer, attribs ); + + if (!pbuffer->texture_format) + { + RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); + return GL_FALSE; + } + return GL_TRUE; +} + static void memory_funcs_init(void) { memory_funcs = osmesa_get_wgl_driver(); @@ -546,6 +854,21 @@ static void display_funcs_init(void) display_funcs->p_wglChoosePixelFormatARB = (void *)1; /* never called */ display_funcs->p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */ display_funcs->p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */ + + if (driver_funcs->p_pbuffer_create) + { + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_pbuffer" ); + display_funcs->p_wglCreatePbufferARB = win32u_wglCreatePbufferARB; + display_funcs->p_wglDestroyPbufferARB = win32u_wglDestroyPbufferARB; + display_funcs->p_wglGetPbufferDCARB = win32u_wglGetPbufferDCARB; + display_funcs->p_wglReleasePbufferDCARB = win32u_wglReleasePbufferDCARB; + display_funcs->p_wglQueryPbufferARB = win32u_wglQueryPbufferARB; + + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_render_texture" ); + display_funcs->p_wglBindTexImageARB = win32u_wglBindTexImageARB; + display_funcs->p_wglReleaseTexImageARB = win32u_wglReleaseTexImageARB; + display_funcs->p_wglSetPbufferAttribARB = win32u_wglSetPbufferAttribARB; + } }
static struct opengl_funcs *get_dc_funcs( HDC hdc, void *null_funcs ) diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 239511b1679..5b100659630 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -236,20 +236,6 @@ struct gl_drawable HDC hdc_dst; };
-struct wgl_pbuffer -{ - struct gl_drawable *gl; - const struct glx_pixel_format* fmt; - int width; - int height; - int pixel_format; - GLint texture_format; - GLuint texture_target; - GLXContext tmp_context; - GLXContext prev_context; - struct list entry; -}; - enum glx_swap_control_method { GLX_SWAP_CONTROL_NONE, @@ -264,7 +250,6 @@ static XContext gl_hwnd_context; static XContext gl_pbuffer_context;
static struct list context_list = LIST_INIT( context_list ); -static struct list pbuffer_list = LIST_INIT( pbuffer_list ); static struct glx_pixel_format *pixel_formats; static int nb_pixel_formats, nb_onscreen_formats;
@@ -1592,19 +1577,10 @@ static struct wgl_context *glxdrv_wglCreateContext( HDC hdc ) */ static BOOL glxdrv_wglDeleteContext(struct wgl_context *ctx) { - struct wgl_pbuffer *pb; - TRACE("(%p)\n", ctx);
pthread_mutex_lock( &context_mutex ); list_remove( &ctx->entry ); - LIST_FOR_EACH_ENTRY( pb, &pbuffer_list, struct wgl_pbuffer, entry ) - { - if (pb->prev_context == ctx->ctx) { - pglXDestroyContext(gdi_display, pb->tmp_context); - pb->prev_context = pb->tmp_context = NULL; - } - } pthread_mutex_unlock( &context_mutex );
if (ctx->ctx) pglXDestroyContext( gdi_display, ctx->ctx ); @@ -1964,409 +1940,69 @@ static struct wgl_context *X11DRV_wglCreateContextAttribsARB( HDC hdc, struct wg return ret; }
-/** - * X11DRV_wglCreatePbufferARB - * - * WGL_ARB_pbuffer: wglCreatePbufferARB - */ -static struct wgl_pbuffer *X11DRV_wglCreatePbufferARB( HDC hdc, int format, int width, int height, - const int *attribs ) +static BOOL x11drv_pbuffer_create( HDC hdc, int format, BOOL largest, int *width, int *height, void **private ) { - int glx_attribs[256], count = 0, value; const struct glx_pixel_format *fmt; - struct wgl_pbuffer *object; + int glx_attribs[7], count = 0; + struct gl_drawable *surface; + RECT rect;
- TRACE( "(%p, %d, %d, %d, %p)\n", hdc, format, width, height, attribs ); + TRACE( "hdc %p, format %d, largest %u, width %d, height %d, private %p\n", hdc, format, largest, *width, *height, private );
/* Convert the WGL pixelformat to a GLX format, if it fails then the format is invalid */ if (!(fmt = get_pixel_format( gdi_display, format, TRUE /* Offscreen */ ))) { ERR( "(%p): invalid pixel format %d\n", hdc, format ); - RtlSetLastWin32Error( ERROR_INVALID_PIXEL_FORMAT ); - return NULL; - } - - if (!(object = calloc( 1, sizeof(*object) ))) - { - RtlSetLastWin32Error( ERROR_NO_SYSTEM_RESOURCES ); - return NULL; + return FALSE; } - object->width = width; - object->height = height; - object->pixel_format = format; - object->fmt = fmt;
glx_attribs[count++] = GLX_PBUFFER_WIDTH; - glx_attribs[count++] = width; + glx_attribs[count++] = *width; glx_attribs[count++] = GLX_PBUFFER_HEIGHT; - glx_attribs[count++] = height; - - while (attribs && 0 != *attribs) + glx_attribs[count++] = *height; + if (largest) { - switch (*attribs) - { - case WGL_PBUFFER_LARGEST_ARB: - ++attribs; - value = *attribs; - TRACE( "WGL_LARGEST_PBUFFER_ARB = %d\n", value ); - glx_attribs[count++] = GLX_LARGEST_PBUFFER; - glx_attribs[count++] = value; - break; - - case WGL_TEXTURE_FORMAT_ARB: - ++attribs; - value = *attribs; - TRACE( "WGL_render_texture Attribute: WGL_TEXTURE_FORMAT_ARB as %x\n", value ); - switch (value) - { - case WGL_NO_TEXTURE_ARB: - object->texture_format = 0; - break; - case WGL_TEXTURE_RGB_ARB: - object->texture_format = GL_RGB; - break; - case WGL_TEXTURE_RGBA_ARB: - object->texture_format = GL_RGBA; - break; - /* WGL_FLOAT_COMPONENTS_NV */ - case WGL_TEXTURE_FLOAT_R_NV: - object->texture_format = GL_FLOAT_R_NV; - break; - case WGL_TEXTURE_FLOAT_RG_NV: - object->texture_format = GL_FLOAT_RG_NV; - break; - case WGL_TEXTURE_FLOAT_RGB_NV: - object->texture_format = GL_FLOAT_RGB_NV; - break; - case WGL_TEXTURE_FLOAT_RGBA_NV: - object->texture_format = GL_FLOAT_RGBA_NV; - break; - default: - ERR( "Unknown texture format: %x\n", value ); - RtlSetLastWin32Error( ERROR_INVALID_DATA ); - goto create_failed; - } - break; - - case WGL_TEXTURE_TARGET_ARB: - ++attribs; - value = *attribs; - TRACE( "WGL_render_texture Attribute: WGL_TEXTURE_TARGET_ARB as %x\n", value ); - switch (value) - { - case WGL_NO_TEXTURE_ARB: - object->texture_target = 0; - break; - case WGL_TEXTURE_CUBE_MAP_ARB: - if (width != height) - { - RtlSetLastWin32Error( ERROR_INVALID_DATA ); - goto create_failed; - } - object->texture_target = GL_TEXTURE_CUBE_MAP; - break; - case WGL_TEXTURE_1D_ARB: - if (1 != height) - { - RtlSetLastWin32Error( ERROR_INVALID_DATA ); - goto create_failed; - } - object->texture_target = GL_TEXTURE_1D; - break; - case WGL_TEXTURE_2D_ARB: - object->texture_target = GL_TEXTURE_2D; - break; - case WGL_TEXTURE_RECTANGLE_NV: - object->texture_target = GL_TEXTURE_RECTANGLE_NV; - break; - default: - ERR( "Unknown texture target: %x\n", value ); - RtlSetLastWin32Error( ERROR_INVALID_DATA ); - goto create_failed; - } - break; - - case WGL_MIPMAP_TEXTURE_ARB: - ++attribs; - value = *attribs; - TRACE( "WGL_render_texture Attribute: WGL_MIPMAP_TEXTURE_ARB as %x\n", value ); - break; - } - ++attribs; + glx_attribs[count++] = GLX_LARGEST_PBUFFER; + glx_attribs[count++] = 1; } glx_attribs[count++] = 0;
- if (!(object->gl = calloc( 1, sizeof(*object->gl) ))) - { - RtlSetLastWin32Error( ERROR_NO_SYSTEM_RESOURCES ); - goto create_failed; - } - object->gl->type = DC_GL_PBUFFER; - object->gl->format = object->fmt; - object->gl->ref = 1; + if (!(surface = calloc( 1, sizeof(*surface) ))) return FALSE; + surface->type = DC_GL_PBUFFER; + surface->format = fmt; + surface->ref = 1;
- object->gl->drawable = pglXCreatePbuffer( gdi_display, fmt->fbconfig, glx_attribs ); - TRACE( "new Pbuffer drawable as %p (%lx)\n", object->gl, object->gl->drawable ); - if (!object->gl->drawable) + surface->drawable = pglXCreatePbuffer( gdi_display, fmt->fbconfig, glx_attribs ); + TRACE( "new Pbuffer drawable as %p (%lx)\n", surface, surface->drawable ); + if (!surface->drawable) { - free( object->gl ); - RtlSetLastWin32Error( ERROR_NO_SYSTEM_RESOURCES ); - goto create_failed; /* unexpected error */ + free( surface ); + return FALSE; } - pthread_mutex_lock( &context_mutex ); - list_add_head( &pbuffer_list, &object->entry ); - pthread_mutex_unlock( &context_mutex ); - TRACE( "->(%p)\n", object ); - return object; - -create_failed: - free( object ); - TRACE( "->(FAILED)\n" ); - return NULL; -} - -/** - * X11DRV_wglDestroyPbufferARB - * - * WGL_ARB_pbuffer: wglDestroyPbufferARB - */ -static BOOL X11DRV_wglDestroyPbufferARB( struct wgl_pbuffer *object ) -{ - TRACE("(%p)\n", object); + pglXQueryDrawable( gdi_display, surface->drawable, GLX_WIDTH, (unsigned int *)width ); + pglXQueryDrawable( gdi_display, surface->drawable, GLX_HEIGHT, (unsigned int *)height ); + SetRect( &rect, 0, 0, *width, *height ); + set_dc_drawable( hdc, surface->drawable, &rect, IncludeInferiors );
pthread_mutex_lock( &context_mutex ); - list_remove( &object->entry ); + XSaveContext( gdi_display, (XID)hdc, gl_pbuffer_context, (char *)surface ); pthread_mutex_unlock( &context_mutex ); - release_gl_drawable( object->gl ); - if (object->tmp_context) - pglXDestroyContext(gdi_display, object->tmp_context); - free( object ); - return GL_TRUE; -} - -/** - * X11DRV_wglGetPbufferDCARB - * - * WGL_ARB_pbuffer: wglGetPbufferDCARB - */ -static HDC X11DRV_wglGetPbufferDCARB( struct wgl_pbuffer *object ) -{ - struct x11drv_escape_set_drawable escape; - struct gl_drawable *prev; - HDC hdc; - - hdc = NtGdiOpenDCW( NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); - if (!hdc) return 0; - - pthread_mutex_lock( &context_mutex ); - if (!XFindContext( gdi_display, (XID)hdc, gl_pbuffer_context, (char **)&prev )) - release_gl_drawable( prev ); - grab_gl_drawable( object->gl ); - XSaveContext( gdi_display, (XID)hdc, gl_pbuffer_context, (char *)object->gl ); - pthread_mutex_unlock( &context_mutex ); - - escape.code = X11DRV_SET_DRAWABLE; - escape.drawable = object->gl->drawable; - escape.mode = IncludeInferiors; - SetRect( &escape.dc_rect, 0, 0, object->width, object->height ); - escape.visual = default_visual; - NtGdiExtEscape( hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); - - NtGdiSetPixelFormat( hdc, object->pixel_format ); - TRACE( "(%p)->(%p)\n", object, hdc ); - return hdc; -} - -/** - * X11DRV_wglQueryPbufferARB - * - * WGL_ARB_pbuffer: wglQueryPbufferARB - */ -static BOOL X11DRV_wglQueryPbufferARB( struct wgl_pbuffer *object, int attrib, int *value ) -{ - TRACE( "(%p, 0x%x, %p)\n", object, attrib, value ); - - switch (attrib) - { - case WGL_PBUFFER_WIDTH_ARB: - pglXQueryDrawable( gdi_display, object->gl->drawable, GLX_WIDTH, (unsigned int *)value ); - break; - case WGL_PBUFFER_HEIGHT_ARB: - pglXQueryDrawable( gdi_display, object->gl->drawable, GLX_HEIGHT, (unsigned int *)value ); - break; - - case WGL_PBUFFER_LOST_ARB: - /* GLX Pbuffers cannot be lost by default. We can support this by - * setting GLX_PRESERVED_CONTENTS to False and using glXSelectEvent - * to receive pixel buffer clobber events, however that may or may - * not give any benefit */ - *value = GL_FALSE; - break;
- case WGL_TEXTURE_FORMAT_ARB: - switch (object->texture_format) - { - case 0: *value = WGL_NO_TEXTURE_ARB; break; - case GL_RGB: *value = WGL_TEXTURE_RGB_ARB; break; - case GL_RGBA: *value = WGL_TEXTURE_RGBA_ARB; break; - /* WGL_FLOAT_COMPONENTS_NV */ - case GL_FLOAT_R_NV: *value = WGL_TEXTURE_FLOAT_R_NV; break; - case GL_FLOAT_RG_NV: *value = WGL_TEXTURE_FLOAT_RG_NV; break; - case GL_FLOAT_RGB_NV: *value = WGL_TEXTURE_FLOAT_RGB_NV; break; - case GL_FLOAT_RGBA_NV: *value = WGL_TEXTURE_FLOAT_RGBA_NV; break; - default: ERR( "Unknown texture format: %x\n", object->texture_format ); - } - break; - - case WGL_TEXTURE_TARGET_ARB: - switch (object->texture_target) - { - case 0: *value = WGL_NO_TEXTURE_ARB; break; - case GL_TEXTURE_1D: *value = WGL_TEXTURE_1D_ARB; break; - case GL_TEXTURE_2D: *value = WGL_TEXTURE_2D_ARB; break; - case GL_TEXTURE_CUBE_MAP: *value = WGL_TEXTURE_CUBE_MAP_ARB; break; - case GL_TEXTURE_RECTANGLE_NV: *value = WGL_TEXTURE_RECTANGLE_NV; break; - } - break; - - case WGL_MIPMAP_TEXTURE_ARB: - *value = GL_FALSE; /** don't support that */ - FIXME( "unsupported WGL_ARB_render_texture attribute query for 0x%x\n", attrib ); - break; - - default: FIXME( "unexpected attribute %x\n", attrib ); break; - } - - return GL_TRUE; + *private = surface; + return TRUE; }
-/** - * X11DRV_wglReleasePbufferDCARB - * - * WGL_ARB_pbuffer: wglReleasePbufferDCARB - */ -static int X11DRV_wglReleasePbufferDCARB( struct wgl_pbuffer *object, HDC hdc ) +static BOOL x11drv_pbuffer_destroy( HDC hdc, void *private ) { - struct gl_drawable *gl; + struct gl_drawable *surface = private;
- TRACE("(%p, %p)\n", object, hdc); + TRACE( "hdc %p, private %p\n", hdc, surface );
pthread_mutex_lock( &context_mutex ); - - if (!XFindContext( gdi_display, (XID)hdc, gl_pbuffer_context, (char **)&gl )) - { - XDeleteContext( gdi_display, (XID)hdc, gl_pbuffer_context ); - release_gl_drawable( gl ); - } - else hdc = 0; - + XDeleteContext( gdi_display, (XID)hdc, gl_pbuffer_context ); pthread_mutex_unlock( &context_mutex ); + release_gl_drawable( surface );
- return hdc && NtGdiDeleteObjectApp(hdc); -} - -/** - * X11DRV_wglSetPbufferAttribARB - * - * WGL_ARB_pbuffer: wglSetPbufferAttribARB - */ -static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int *piAttribList ) -{ - WARN("(%p, %p): alpha-testing, report any problem\n", object, piAttribList); - - if (!object->texture_format) - { - RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - return GL_FALSE; - } - return GL_TRUE; -} - -static GLenum binding_from_target( GLenum target ) -{ - switch (target) - { - case GL_TEXTURE_CUBE_MAP: return GL_TEXTURE_BINDING_CUBE_MAP; - case GL_TEXTURE_1D: return GL_TEXTURE_BINDING_1D; - case GL_TEXTURE_2D: return GL_TEXTURE_BINDING_2D; - case GL_TEXTURE_RECTANGLE_NV: return GL_TEXTURE_BINDING_RECTANGLE_NV; - } - FIXME( "Unsupported target %#x\n", target ); - return 0; -} - -/** - * X11DRV_wglBindTexImageARB - * - * WGL_ARB_render_texture: wglBindTexImageARB - */ -static BOOL X11DRV_wglBindTexImageARB( struct wgl_pbuffer *object, int iBuffer ) -{ - static BOOL initialized = FALSE; - int prev_binded_texture = 0; - GLXContext prev_context; - GLXDrawable prev_drawable; - - TRACE("(%p, %d)\n", object, iBuffer); - - if (!object->texture_format) - { - RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - return GL_FALSE; - } - - prev_context = pglXGetCurrentContext(); - prev_drawable = pglXGetCurrentDrawable(); - - /* Our render_texture emulation is basic and lacks some features (1D/Cube support). - This is mostly due to lack of demos/games using them. Further the use of glReadPixels - isn't ideal performance wise but I wasn't able to get other ways working. - */ - if (!initialized) - { - initialized = TRUE; /* Only show the FIXME once for performance reasons */ - FIXME( "partial stub!\n" ); - } - - TRACE( "drawable=%p (%lx), context=%p\n", object->gl, object->gl->drawable, prev_context ); - if (!object->tmp_context || object->prev_context != prev_context) - { - if (object->tmp_context) pglXDestroyContext( gdi_display, object->tmp_context ); - object->tmp_context = pglXCreateNewContext( gdi_display, object->fmt->fbconfig, - object->fmt->render_type, prev_context, True ); - object->prev_context = prev_context; - } - - opengl_funcs.p_glGetIntegerv( binding_from_target( object->texture_target ), &prev_binded_texture ); - - /* Switch to our pbuffer */ - pglXMakeCurrent( gdi_display, object->gl->drawable, object->tmp_context ); - - /* Make sure that the prev_binded_texture is set as the current texture state isn't shared - * between contexts. After that copy the pbuffer texture data. */ - opengl_funcs.p_glBindTexture( object->texture_target, prev_binded_texture ); - opengl_funcs.p_glCopyTexImage2D( object->texture_target, 0, object->texture_format, 0, 0, - object->width, object->height, 0 ); - - /* Switch back to the original drawable and context */ - pglXMakeCurrent( gdi_display, prev_drawable, prev_context ); - return GL_TRUE; -} - -/** - * X11DRV_wglReleaseTexImageARB - * - * WGL_ARB_render_texture: wglReleaseTexImageARB - */ -static BOOL X11DRV_wglReleaseTexImageARB( struct wgl_pbuffer *object, int iBuffer ) -{ - TRACE("(%p, %d)\n", object, iBuffer); - - if (!object->texture_format) - { - RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - return GL_FALSE; - } return GL_TRUE; }
@@ -2506,17 +2142,6 @@ static const char *x11drv_init_wgl_extensions(void)
if (has_extension( glxExtensions, "GLX_ARB_multisample")) register_extension( "WGL_ARB_multisample" );
- if (glxRequireVersion(3)) - { - register_extension( "WGL_ARB_pbuffer" ); - opengl_funcs.p_wglCreatePbufferARB = X11DRV_wglCreatePbufferARB; - opengl_funcs.p_wglDestroyPbufferARB = X11DRV_wglDestroyPbufferARB; - opengl_funcs.p_wglGetPbufferDCARB = X11DRV_wglGetPbufferDCARB; - opengl_funcs.p_wglQueryPbufferARB = X11DRV_wglQueryPbufferARB; - opengl_funcs.p_wglReleasePbufferDCARB = X11DRV_wglReleasePbufferDCARB; - opengl_funcs.p_wglSetPbufferAttribARB = X11DRV_wglSetPbufferAttribARB; - } - if (has_extension( glxExtensions, "GLX_ARB_fbconfig_float")) { register_extension("WGL_ARB_pixel_format_float"); @@ -2526,10 +2151,6 @@ static const char *x11drv_init_wgl_extensions(void) /* Support WGL_ARB_render_texture when there's support or pbuffer based emulation */ if (has_extension( glxExtensions, "GLX_ARB_render_texture" ) || glxRequireVersion( 3 )) { - register_extension( "WGL_ARB_render_texture" ); - opengl_funcs.p_wglBindTexImageARB = X11DRV_wglBindTexImageARB; - opengl_funcs.p_wglReleaseTexImageARB = X11DRV_wglReleaseTexImageARB; - /* The WGL version of GLX_NV_float_buffer requires render_texture */ if (has_extension( glxExtensions, "GLX_NV_float_buffer")) register_extension("WGL_NV_float_buffer"); @@ -2678,6 +2299,8 @@ static const struct opengl_driver_funcs x11drv_driver_funcs = .p_describe_pixel_format = x11drv_describe_pixel_format, .p_init_wgl_extensions = x11drv_init_wgl_extensions, .p_set_pixel_format = x11drv_set_pixel_format, + .p_pbuffer_create = x11drv_pbuffer_create, + .p_pbuffer_destroy = x11drv_pbuffer_destroy, };
static struct opengl_funcs opengl_funcs = diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index f652a58c920..11bcbe6758a 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -117,6 +117,9 @@ struct opengl_driver_funcs BOOL (*p_describe_pixel_format)(int,struct wgl_pixel_format*); const char *(*p_init_wgl_extensions)(void); BOOL (*p_set_pixel_format)(HWND,int,int,BOOL); + + BOOL (*p_pbuffer_create)(HDC,int,BOOL,GLsizei*,GLsizei*,void **); + BOOL (*p_pbuffer_destroy)(HDC,void*); };
#endif /* WINE_UNIX_LIB */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 361 +++------------------------------- 1 file changed, 27 insertions(+), 334 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 9c4e7234d3d..cb15846ae53 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -79,14 +79,13 @@ DECL_FUNCPTR(glClear); static pthread_mutex_t gl_object_mutex = PTHREAD_MUTEX_INITIALIZER; static struct list gl_drawables = LIST_INIT(gl_drawables); static struct list gl_contexts = LIST_INIT(gl_contexts); -static struct list gl_pbuffer_dcs = LIST_INIT(gl_pbuffer_dcs); -static struct list gl_pbuffers = LIST_INIT(gl_pbuffers);
struct wayland_gl_drawable { struct list entry; LONG ref; HWND hwnd; + HDC hdc; struct wayland_client_surface *client; struct wl_egl_window *wl_egl_window; EGLSurface surface; @@ -126,16 +125,10 @@ struct wayland_pbuffer_dc static struct wayland_gl_drawable *find_drawable(HWND hwnd, HDC hdc) { struct wayland_gl_drawable *gl; - struct wayland_pbuffer_dc *pb; - if (hwnd) - { - LIST_FOR_EACH_ENTRY(gl, &gl_drawables, struct wayland_gl_drawable, entry) - if (gl->hwnd == hwnd) return gl; - } - if (hdc) + LIST_FOR_EACH_ENTRY(gl, &gl_drawables, struct wayland_gl_drawable, entry) { - LIST_FOR_EACH_ENTRY(pb, &gl_pbuffer_dcs, struct wayland_pbuffer_dc, entry) - if (pb->hdc == hdc) return pb->gl; + if (hwnd && gl->hwnd == hwnd) return gl; + if (hdc && gl->hdc == hdc) return gl; } return NULL; } @@ -189,11 +182,9 @@ static inline EGLConfig egl_config_for_format(int format) return egl_configs[format - num_egl_configs - 1]; }
-static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int format) +static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, HDC hdc, int format, int width, int height) { struct wayland_gl_drawable *gl; - int client_width, client_height; - RECT client_rect = {0}; const EGLint attribs[] = {EGL_PRESENT_OPAQUE_EXT, EGL_TRUE, EGL_NONE};
TRACE("hwnd=%p format=%d\n", hwnd, format); @@ -203,20 +194,15 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for
gl->ref = 1; gl->hwnd = hwnd; + gl->hdc = hdc; gl->swap_interval = 1;
- NtUserGetClientRect(gl->hwnd, &client_rect, NtUserGetDpiForWindow(gl->hwnd)); - client_width = client_rect.right - client_rect.left; - client_height = client_rect.bottom - client_rect.top; - if (client_width == 0 || client_height == 0) client_width = client_height = 1; - /* Get the client surface for the HWND. If don't have a wayland surface * (e.g., HWND_MESSAGE windows) just create a dummy surface to act as the * target render surface. */ if (!(gl->client = get_client_surface(hwnd))) goto err;
- gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, - client_width, client_height); + gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, width, height); if (!gl->wl_egl_window) { ERR("Failed to create wl_egl_window\n"); @@ -435,6 +421,7 @@ static void wgl_context_refresh(struct wgl_context *ctx) static BOOL wayland_set_pixel_format(HWND hwnd, int old_format, int new_format, BOOL internal) { struct wayland_gl_drawable *gl; + RECT rect;
/* Even for internal pixel format fail setting it if the app has already set a * different pixel format. Let wined3d create a backup GL context instead. @@ -442,7 +429,11 @@ static BOOL wayland_set_pixel_format(HWND hwnd, int old_format, int new_format, * than blitting from backup context. */ if (old_format) return old_format == new_format;
- if (!(gl = wayland_gl_drawable_create(hwnd, new_format))) return FALSE; + NtUserGetClientRect(hwnd, &rect, NtUserGetDpiForWindow(hwnd)); + if (rect.right == rect.left) rect.right = rect.left + 1; + if (rect.bottom == rect.top) rect.bottom = rect.top + 1; + + if (!(gl = wayland_gl_drawable_create(hwnd, 0, new_format, rect.right - rect.left, rect.bottom - rect.top))) return FALSE; wayland_update_gl_drawable(hwnd, gl); return TRUE; } @@ -490,41 +481,6 @@ out: return ctx; }
-static struct wayland_gl_drawable *clear_pbuffer_dc(HDC hdc) -{ - struct wayland_pbuffer_dc *pd; - struct wayland_gl_drawable *gl; - - LIST_FOR_EACH_ENTRY(pd, &gl_pbuffer_dcs, struct wayland_pbuffer_dc, entry) - { - if (pd->hdc == hdc) - { - list_remove(&pd->entry); - gl = pd->gl; - free(pd); - return gl; - } - } - - return NULL; -} - -static BOOL set_pbuffer_dc(struct wgl_pbuffer *pbuffer, HDC hdc) -{ - struct wayland_pbuffer_dc *pd; - - if (!(pd = calloc(1, sizeof(*pd)))) - { - ERR("Failed to allocate memory for pbuffer HDC mapping\n"); - return FALSE; - } - pd->hdc = hdc; - pd->gl = wayland_gl_drawable_acquire(pbuffer->gl); - list_add_head(&gl_pbuffer_dcs, &pd->entry); - - return TRUE; -} - void wayland_glClear(GLbitfield mask) { struct wgl_context *ctx = NtCurrentTeb()->glContext; @@ -557,18 +513,8 @@ static struct wgl_context *wayland_wglCreateContextAttribsARB(HDC hdc,
static BOOL wayland_wglDeleteContext(struct wgl_context *ctx) { - struct wgl_pbuffer *pb; - pthread_mutex_lock(&gl_object_mutex); list_remove(&ctx->entry); - LIST_FOR_EACH_ENTRY(pb, &gl_pbuffers, struct wgl_pbuffer, entry) - { - if (pb->prev_context == ctx->context) - { - p_eglDestroyContext(egl_display, pb->tmp_context); - pb->prev_context = pb->tmp_context = NULL; - } - } pthread_mutex_unlock(&gl_object_mutex); p_eglDestroyContext(egl_display, ctx->context); if (ctx->draw) wayland_gl_drawable_release(ctx->draw); @@ -717,278 +663,35 @@ static BOOL wayland_wglSwapIntervalEXT(int interval) return ret; }
-static struct wgl_pbuffer *wayland_wglCreatePbufferARB(HDC hdc, int format, - int width, int height, - const int *attribs) +static BOOL wayland_pbuffer_create(HDC hdc, int format, BOOL largest, int *width, int *height, void **private) { - struct wgl_pbuffer *pbuffer; + struct wayland_gl_drawable *drawable;
- TRACE("(%p, %d, %d, %d, %p)\n", hdc, format, width, height, attribs); - - if (format <= 0 || format > 2 * num_egl_configs) - { - RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT); - ERR("Invalid format %d\n", format); - return NULL; - } + TRACE("hdc %p, format %d, largest %u, width %d, height %d, private %p\n", hdc, format, largest, *width, *height, private);
/* Use an unmapped wayland surface as our offscreen "pbuffer" surface. */ - if (!(pbuffer = calloc(1, sizeof(*pbuffer))) || - !(pbuffer->gl = wayland_gl_drawable_create(0, format))) - { - RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); - free(pbuffer); - return NULL; - } - - pbuffer->width = width; - pbuffer->height = height; - pbuffer->pixel_format = format; - wl_egl_window_resize(pbuffer->gl->wl_egl_window, width, height, 0, 0); - - for (; attribs && attribs[0]; attribs += 2) - { - switch (attribs[0]) - { - case WGL_TEXTURE_FORMAT_ARB: - TRACE("attribs[WGL_TEXTURE_FORMAT_ARB]=0x%x\n", attribs[1]); - switch(attribs[1]) - { - case WGL_NO_TEXTURE_ARB: - pbuffer->texture_format = 0; - break; - case WGL_TEXTURE_RGB_ARB: - pbuffer->texture_format = GL_RGB; - break; - case WGL_TEXTURE_RGBA_ARB: - pbuffer->texture_format = GL_RGBA; - break; - /* WGL_FLOAT_COMPONENTS_NV */ - case WGL_TEXTURE_FLOAT_R_NV: - pbuffer->texture_format = GL_FLOAT_R_NV; - break; - case WGL_TEXTURE_FLOAT_RG_NV: - pbuffer->texture_format = GL_FLOAT_RG_NV; - break; - case WGL_TEXTURE_FLOAT_RGB_NV: - pbuffer->texture_format = GL_FLOAT_RGB_NV; - break; - case WGL_TEXTURE_FLOAT_RGBA_NV: - pbuffer->texture_format = GL_FLOAT_RGBA_NV; - break; - default: - ERR("Unknown texture format: %x\n", attribs[1]); - } - break; - - case WGL_TEXTURE_TARGET_ARB: - TRACE("attribs[WGL_TEXTURE_TARGET_ARB]=0x%x\n", attribs[1]); - switch (attribs[1]) - { - case WGL_TEXTURE_CUBE_MAP_ARB: - if (width != height) goto err; - pbuffer->texture_target = GL_TEXTURE_CUBE_MAP; - pbuffer->texture_binding = GL_TEXTURE_BINDING_CUBE_MAP; - break; - case WGL_TEXTURE_1D_ARB: - if (height != 1) goto err; - pbuffer->texture_target = GL_TEXTURE_1D; - pbuffer->texture_binding = GL_TEXTURE_BINDING_1D; - break; - case WGL_TEXTURE_2D_ARB: - pbuffer->texture_target = GL_TEXTURE_2D; - pbuffer->texture_binding = GL_TEXTURE_BINDING_2D; - break; - case WGL_TEXTURE_RECTANGLE_NV: - pbuffer->texture_target = GL_TEXTURE_RECTANGLE_NV; - pbuffer->texture_binding = GL_TEXTURE_BINDING_RECTANGLE_NV; - break; - default: - ERR("Unknown texture target: %x\n", attribs[1]); - goto err; - } - break; - - case WGL_MIPMAP_TEXTURE_ARB: - TRACE("attribs[WGL_MIPMAP_TEXTURE_ARB]=0x%x\n", attribs[1]); - break; - - default: - WARN("Unknown attribute: %x\n", attribs[0]); - break; - } - } - - pthread_mutex_lock(&gl_object_mutex); - list_add_head(&gl_pbuffers, &pbuffer->entry); - pthread_mutex_unlock(&gl_object_mutex); - - return pbuffer; - -err: - RtlSetLastWin32Error(ERROR_INVALID_DATA); - wayland_gl_drawable_release(pbuffer->gl); - free(pbuffer); - return NULL; -} - -static BOOL wayland_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer) -{ - TRACE("(%p)\n", pbuffer); - - pthread_mutex_lock(&gl_object_mutex); - list_remove(&pbuffer->entry); - pthread_mutex_unlock(&gl_object_mutex); - - if (pbuffer->tmp_context) p_eglDestroyContext(egl_display, pbuffer->tmp_context); - wayland_gl_drawable_release(pbuffer->gl); - free(pbuffer); - - return GL_TRUE; -} - -static HDC wayland_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer) -{ - HDC hdc; - BOOL set; - struct wayland_gl_drawable *old; - - if (!(hdc = NtGdiOpenDCW(NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL))) return 0; + if (!(drawable = wayland_gl_drawable_create(0, hdc, format, *width, *height))) return FALSE;
pthread_mutex_lock(&gl_object_mutex); - old = clear_pbuffer_dc(hdc); - set = set_pbuffer_dc(pbuffer, hdc); + list_add_head(&gl_drawables, &drawable->entry); pthread_mutex_unlock(&gl_object_mutex);
- if (old) wayland_gl_drawable_release(old); - if (!set) - { - NtGdiDeleteObjectApp(hdc); - return 0; - } - - NtGdiSetPixelFormat(hdc, pbuffer->pixel_format); - return hdc; + *private = drawable; + return TRUE; }
-static BOOL wayland_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int attrib, int *value) +static BOOL wayland_pbuffer_destroy(HDC hdc, void *private) { - TRACE("(%p, 0x%x, %p)\n", pbuffer, attrib, value); - - switch (attrib) - { - case WGL_PBUFFER_WIDTH_ARB: *value = pbuffer->width; break; - case WGL_PBUFFER_HEIGHT_ARB: *value = pbuffer->height; break; - case WGL_PBUFFER_LOST_ARB: *value = GL_FALSE; break; - case WGL_TEXTURE_FORMAT_ARB: - switch(pbuffer->texture_format) - { - case GL_RGB: *value = WGL_TEXTURE_RGB_ARB; break; - case GL_RGBA: *value = WGL_TEXTURE_RGBA_ARB; break; - case GL_FLOAT_R_NV: *value = WGL_TEXTURE_FLOAT_R_NV; break; - case GL_FLOAT_RG_NV: *value = WGL_TEXTURE_FLOAT_RG_NV; break; - case GL_FLOAT_RGB_NV: *value = WGL_TEXTURE_FLOAT_RGB_NV; break; - case GL_FLOAT_RGBA_NV: *value = WGL_TEXTURE_FLOAT_RGBA_NV; break; - default: - ERR("Unknown texture format: %x\n", pbuffer->texture_format); - break; - } - break; - case WGL_TEXTURE_TARGET_ARB: - switch (pbuffer->texture_target) - { - case GL_TEXTURE_1D: *value = WGL_TEXTURE_1D_ARB; break; - case GL_TEXTURE_2D: *value = WGL_TEXTURE_2D_ARB; break; - case GL_TEXTURE_CUBE_MAP: *value = WGL_TEXTURE_CUBE_MAP_ARB; break; - case GL_TEXTURE_RECTANGLE_NV: *value = WGL_TEXTURE_RECTANGLE_NV; break; - default: - ERR("Unknown texture target: %x\n", pbuffer->texture_target); - break; - } - break; - case WGL_MIPMAP_TEXTURE_ARB: - *value = GL_FALSE; - FIXME("unsupported attribute query for 0x%x\n", attrib); - break; - default: - FIXME("unexpected attribute %x\n", attrib); - break; - } - - return GL_TRUE; -} + struct wayland_gl_drawable *drawable = private;
-static int wayland_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc) -{ - struct wayland_gl_drawable *old; + TRACE("hdc %p, private %p\n", hdc, private);
pthread_mutex_lock(&gl_object_mutex); - old = clear_pbuffer_dc(hdc); + list_remove(&drawable->entry); pthread_mutex_unlock(&gl_object_mutex);
- if (old) wayland_gl_drawable_release(old); - else hdc = 0; - - return hdc && NtGdiDeleteObjectApp(hdc); -} - -static BOOL wayland_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int buffer) -{ - EGLContext prev_context = p_eglGetCurrentContext(); - EGLSurface prev_draw = p_eglGetCurrentSurface(EGL_DRAW); - EGLSurface prev_read = p_eglGetCurrentSurface(EGL_READ); - int prev_bound_texture = 0; - - TRACE("(%p, %d)\n", pbuffer, buffer); - - if (!pbuffer->tmp_context || pbuffer->prev_context != prev_context) - { - if (pbuffer->tmp_context) p_eglDestroyContext(egl_display, pbuffer->tmp_context); - p_eglBindAPI(EGL_OPENGL_API); - pbuffer->tmp_context = - p_eglCreateContext(egl_display, EGL_NO_CONFIG_KHR, prev_context, NULL); - pbuffer->prev_context = prev_context; - } - - opengl_funcs.p_glGetIntegerv(pbuffer->texture_binding, &prev_bound_texture); - - p_eglMakeCurrent(egl_display, pbuffer->gl->surface, pbuffer->gl->surface, - pbuffer->tmp_context); - - /* Make sure that the prev_bound_texture is set as the current texture - * state isn't shared between contexts. After that copy the pbuffer texture - * data. Note that at the moment we ignore the 'buffer' argument and always - * copy from the pbuffer back buffer. */ - opengl_funcs.p_glBindTexture(pbuffer->texture_target, prev_bound_texture); - opengl_funcs.p_glCopyTexImage2D(pbuffer->texture_target, 0, - pbuffer->texture_format, 0, 0, - pbuffer->width, pbuffer->height, 0); + wayland_gl_drawable_release(drawable);
- /* Switch back to the original surface and context. */ - p_eglMakeCurrent(egl_display, prev_draw, prev_read, prev_context); - - return GL_TRUE; -} - -static BOOL wayland_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int buffer) -{ - TRACE("(%p, %d)\n", pbuffer, buffer); - - if (!pbuffer->texture_format) - { - RtlSetLastWin32Error(ERROR_INVALID_HANDLE); - return GL_FALSE; - } - return GL_TRUE; -} - -static BOOL wayland_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *attribs) -{ - if (!pbuffer->texture_format) - { - RtlSetLastWin32Error(ERROR_INVALID_HANDLE); - return GL_FALSE; - } return GL_TRUE; }
@@ -1191,18 +894,6 @@ static const char *wayland_init_wgl_extensions(void) register_extension("WGL_ATI_pixel_format_float"); }
- register_extension("WGL_ARB_pbuffer"); - opengl_funcs.p_wglCreatePbufferARB = wayland_wglCreatePbufferARB; - opengl_funcs.p_wglDestroyPbufferARB = wayland_wglDestroyPbufferARB; - opengl_funcs.p_wglGetPbufferDCARB = wayland_wglGetPbufferDCARB; - opengl_funcs.p_wglQueryPbufferARB = wayland_wglQueryPbufferARB; - opengl_funcs.p_wglReleasePbufferDCARB = wayland_wglReleasePbufferDCARB; - - register_extension("WGL_ARB_render_texture"); - opengl_funcs.p_wglBindTexImageARB = wayland_wglBindTexImageARB; - opengl_funcs.p_wglReleaseTexImageARB = wayland_wglReleaseTexImageARB; - opengl_funcs.p_wglSetPbufferAttribARB = wayland_wglSetPbufferAttribARB; - return wgl_extensions; }
@@ -1267,6 +958,8 @@ static const struct opengl_driver_funcs wayland_driver_funcs = .p_describe_pixel_format = wayland_describe_pixel_format, .p_init_wgl_extensions = wayland_init_wgl_extensions, .p_set_pixel_format = wayland_set_pixel_format, + .p_pbuffer_create = wayland_pbuffer_create, + .p_pbuffer_destroy = wayland_pbuffer_destroy, };
/**********************************************************************
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 146 +++++++++- dlls/winemac.drv/opengl.c | 524 ++++------------------------------ dlls/winewayland.drv/opengl.c | 20 +- dlls/winex11.drv/opengl.c | 20 +- include/wine/opengl_driver.h | 4 +- 5 files changed, 227 insertions(+), 487 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 00b74b0311e..941a5e5de22 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -50,6 +50,8 @@ struct wgl_pbuffer GLsizei height; GLenum texture_format; GLenum texture_target; + GLint mipmap_level; + GLenum cube_face;
struct wgl_context *tmp_context; struct wgl_context *prev_context; @@ -525,9 +527,9 @@ static void win32u_get_pixel_formats( struct wgl_pixel_format *formats, UINT max static struct wgl_pbuffer *win32u_wglCreatePbufferARB( HDC hdc, int format, int width, int height, const int *attribs ) { + UINT total, onscreen, size, max_level = 0; struct wgl_pbuffer *pbuffer; struct opengl_funcs *funcs; - UINT total, onscreen; BOOL largest = FALSE;
TRACE( "(%p, %d, %d, %d, %p)\n", hdc, format, width, height, attribs ); @@ -556,6 +558,7 @@ static struct wgl_pbuffer *win32u_wglCreatePbufferARB( HDC hdc, int format, int pbuffer->funcs = funcs; pbuffer->width = width; pbuffer->height = height; + pbuffer->mipmap_level = -1;
for (; attribs && attribs[0]; attribs += 2) { @@ -627,6 +630,11 @@ static struct wgl_pbuffer *win32u_wglCreatePbufferARB( HDC hdc, int format, int
case WGL_MIPMAP_TEXTURE_ARB: TRACE( "WGL_MIPMAP_TEXTURE_ARB %#x\n", attribs[1] ); + if (attribs[1]) + { + pbuffer->mipmap_level = max_level = 0; + for (size = min( width, height ) / 2; size; size /= 2) max_level++; + } break;
default: @@ -635,7 +643,8 @@ static struct wgl_pbuffer *win32u_wglCreatePbufferARB( HDC hdc, int format, int } }
- if (pbuffer->driver_funcs->p_pbuffer_create( pbuffer->hdc, format, largest, &pbuffer->width, + if (pbuffer->driver_funcs->p_pbuffer_create( pbuffer->hdc, format, largest, pbuffer->texture_format, + pbuffer->texture_target, max_level, &pbuffer->width, &pbuffer->height, &pbuffer->driver_private )) { pthread_mutex_lock( &pbuffer_mutex ); @@ -722,8 +731,34 @@ static BOOL win32u_wglQueryPbufferARB( struct wgl_pbuffer *pbuffer, int attrib, break;
case WGL_MIPMAP_TEXTURE_ARB: - *value = GL_FALSE; - FIXME( "WGL_MIPMAP_TEXTURE_ARB not supported\n" ); + *value = pbuffer->mipmap_level >= 0; + break; + case WGL_MIPMAP_LEVEL_ARB: + *value = max( pbuffer->mipmap_level, 0 ); + break; + case WGL_CUBE_MAP_FACE_ARB: + switch (pbuffer->cube_face) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + default: + *value = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + *value = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + *value = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + *value = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + *value = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + *value = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; + break; + } break;
default: @@ -750,8 +785,11 @@ static GLenum binding_from_target( GLenum target ) static BOOL win32u_wglBindTexImageARB( struct wgl_pbuffer *pbuffer, int buffer ) { HDC prev_draw = NtCurrentTeb()->glReserved1[0], prev_read = NtCurrentTeb()->glReserved1[1]; + int prev_texture = 0, format = win32u_wglGetPixelFormat( pbuffer->hdc ); struct wgl_context *prev_context = NtCurrentTeb()->glContext; - int prev_texture = 0; + struct wgl_pixel_format desc; + GLenum source; + UINT ret;
TRACE( "pbuffer %p, buffer %d\n", pbuffer, buffer );
@@ -761,6 +799,52 @@ static BOOL win32u_wglBindTexImageARB( struct wgl_pbuffer *pbuffer, int buffer ) return GL_FALSE; }
+ if (!pbuffer->driver_funcs->p_describe_pixel_format( format, &desc )) + { + RtlSetLastWin32Error( ERROR_INVALID_PIXEL_FORMAT ); + return FALSE; + } + + switch (buffer) + { + case WGL_FRONT_LEFT_ARB: + if (desc.pfd.dwFlags & PFD_STEREO) source = GL_FRONT_LEFT; + else source = GL_FRONT; + break; + case WGL_FRONT_RIGHT_ARB: + source = GL_FRONT_RIGHT; + break; + case WGL_BACK_LEFT_ARB: + if (desc.pfd.dwFlags & PFD_STEREO) source = GL_BACK_LEFT; + else source = GL_BACK; + break; + case WGL_BACK_RIGHT_ARB: + source = GL_BACK_RIGHT; + break; + case WGL_AUX0_ARB: source = GL_AUX0; break; + case WGL_AUX1_ARB: source = GL_AUX1; break; + case WGL_AUX2_ARB: source = GL_AUX2; break; + case WGL_AUX3_ARB: source = GL_AUX3; break; + + case WGL_AUX4_ARB: + case WGL_AUX5_ARB: + case WGL_AUX6_ARB: + case WGL_AUX7_ARB: + case WGL_AUX8_ARB: + case WGL_AUX9_ARB: + FIXME( "Unsupported source buffer %#x\n", buffer ); + RtlSetLastWin32Error( ERROR_INVALID_DATA ); + return GL_FALSE; + + default: + WARN( "Unknown source buffer %#x\n", buffer ); + RtlSetLastWin32Error( ERROR_INVALID_DATA ); + return GL_FALSE; + } + + if ((ret = pbuffer->driver_funcs->p_pbuffer_bind( pbuffer->hdc, pbuffer->driver_private, source )) != -1) + return ret; + if (!pbuffer->tmp_context || pbuffer->prev_context != prev_context) { pthread_mutex_lock( &pbuffer_mutex ); @@ -795,7 +879,8 @@ static BOOL win32u_wglReleaseTexImageARB( struct wgl_pbuffer *pbuffer, int buffe RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return GL_FALSE; } - return GL_TRUE; + + return !!pbuffer->driver_funcs->p_pbuffer_bind( pbuffer->hdc, pbuffer->driver_private, GL_NONE ); }
static BOOL win32u_wglSetPbufferAttribARB( struct wgl_pbuffer *pbuffer, const int *attribs ) @@ -807,7 +892,54 @@ static BOOL win32u_wglSetPbufferAttribARB( struct wgl_pbuffer *pbuffer, const in RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return GL_FALSE; } - return GL_TRUE; + + for (; attribs && attribs[0]; attribs += 2) + { + switch (attribs[0]) + { + case WGL_MIPMAP_LEVEL_ARB: + TRACE( "WGL_MIPMAP_LEVEL_ARB %#x\n", attribs[1] ); + pbuffer->mipmap_level = attribs[1]; + break; + + case WGL_CUBE_MAP_FACE_ARB: + TRACE( "WGL_CUBE_MAP_FACE_ARB %#x\n", attribs[1] ); + switch (attribs[1]) + { + case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + pbuffer->cube_face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + break; + case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + pbuffer->cube_face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; + break; + case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + pbuffer->cube_face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; + break; + case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + pbuffer->cube_face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; + break; + case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + pbuffer->cube_face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; + break; + case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + pbuffer->cube_face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; + break; + default: + FIXME( "Unknown texture face: %x\n", attribs[1] ); + RtlSetLastWin32Error( ERROR_INVALID_DATA ); + return GL_FALSE; + } + break; + + default: + FIXME( "Invalid attribute 0x%x\n", attribs[0] ); + RtlSetLastWin32Error( ERROR_INVALID_DATA ); + return GL_FALSE; + } + } + + return pbuffer->driver_funcs->p_pbuffer_updated( pbuffer->hdc, pbuffer->driver_private, + pbuffer->cube_face, max( pbuffer->mipmap_level, 0 ) ); }
static void memory_funcs_init(void) diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index f6b0ff90d7f..3d9607d2dbf 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -67,10 +67,12 @@ struct wgl_context HWND draw_hwnd; macdrv_view draw_view; RECT draw_rect; - struct wgl_pbuffer *draw_pbuffer; + CGLPBufferObj draw_pbuffer; + GLenum draw_pbuffer_face; + GLint draw_pbuffer_level; macdrv_view read_view; RECT read_rect; - struct wgl_pbuffer *read_pbuffer; + CGLPBufferObj read_pbuffer; BOOL has_been_current; BOOL sharing; LONG update_swap_interval; @@ -82,17 +84,6 @@ struct wgl_context static struct list context_list = LIST_INIT(context_list); static pthread_mutex_t context_mutex = PTHREAD_MUTEX_INITIALIZER;
- -struct wgl_pbuffer -{ - CGLPBufferObj pbuffer; - int format; - BOOL no_texture; - int max_level; - GLint level; - GLenum face; -}; - static CFMutableDictionaryRef dc_pbuffers; static pthread_mutex_t dc_pbuffers_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -1544,7 +1535,7 @@ static void make_context_current(struct wgl_context *context, BOOL read) { macdrv_view view; RECT view_rect; - struct wgl_pbuffer *pbuffer; + CGLPBufferObj pbuffer;
if (read) { @@ -1569,8 +1560,7 @@ static void make_context_current(struct wgl_context *context, BOOL read)
if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled) CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize); - CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face, - pbuffer->level, 0); + CGLSetPBuffer(context->cglcontext, pbuffer, context->draw_pbuffer_face, context->draw_pbuffer_level, 0); CGLSetCurrentContext(context->cglcontext); } } @@ -2210,65 +2200,18 @@ static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) * * WGL_ARB_render_texture: wglBindTexImageARB */ -static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer) +static UINT macdrv_pbuffer_bind(HDC hdc, void *private, GLenum source) { struct wgl_context *context = NtCurrentTeb()->glContext; - GLenum source; + CGLPBufferObj pbuffer = private; CGLError err;
- TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer); + TRACE("hdc %p pbuffer %p source 0x%x\n", hdc, pbuffer, source);
- if (pbuffer->no_texture) - { - RtlSetLastWin32Error(ERROR_INVALID_OPERATION); - return GL_FALSE; - } - - if (!context->draw_view && context->draw_pbuffer == pbuffer) + if (!context->draw_view && context->draw_pbuffer == pbuffer && source != GL_NONE) opengl_funcs.p_glFlush();
- switch (iBuffer) - { - case WGL_FRONT_LEFT_ARB: - if (pixel_formats[pbuffer->format - 1].stereo) - source = GL_FRONT_LEFT; - else - source = GL_FRONT; - break; - case WGL_FRONT_RIGHT_ARB: - source = GL_FRONT_RIGHT; - break; - case WGL_BACK_LEFT_ARB: - if (pixel_formats[pbuffer->format - 1].stereo) - source = GL_BACK_LEFT; - else - source = GL_BACK; - break; - case WGL_BACK_RIGHT_ARB: - source = GL_BACK_RIGHT; - break; - case WGL_AUX0_ARB: source = GL_AUX0; break; - case WGL_AUX1_ARB: source = GL_AUX1; break; - case WGL_AUX2_ARB: source = GL_AUX2; break; - case WGL_AUX3_ARB: source = GL_AUX3; break; - - case WGL_AUX4_ARB: - case WGL_AUX5_ARB: - case WGL_AUX6_ARB: - case WGL_AUX7_ARB: - case WGL_AUX8_ARB: - case WGL_AUX9_ARB: - FIXME("unsupported source buffer 0x%x\n", iBuffer); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - return GL_FALSE; - - default: - WARN("unknown source buffer 0x%x\n", iBuffer); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - return GL_FALSE; - } - - err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source); + err = CGLTexImagePBuffer(context->cglcontext, pbuffer, source); if (err != kCGLNoError) { WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err)); @@ -2459,191 +2402,46 @@ static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc, return context; }
- -/********************************************************************** - * macdrv_wglCreatePbufferARB - * - * WGL_ARB_pbuffer: wglCreatePbufferARB - */ -static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight, - const int *piAttribList) +static BOOL macdrv_pbuffer_create(HDC hdc, int format, BOOL largest, GLenum texture_format, GLenum texture_target, + GLint max_level, GLsizei *width, GLsizei *height, void **private) { - struct wgl_pbuffer* pbuffer; - GLenum target = 0; - GLenum internalFormat = 0; CGLError err;
- TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n", - hdc, iPixelFormat, iWidth, iHeight, piAttribList); - - if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer) - { - WARN("invalid pixel format %d\n", iPixelFormat); - RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT); - return NULL; - } - - pbuffer = calloc(1, sizeof(*pbuffer)); - pbuffer->format = iPixelFormat; - - for ( ; piAttribList && *piAttribList; piAttribList += 2) - { - int attr = piAttribList[0]; - int value = piAttribList[1]; - - switch (attr) - { - case WGL_PBUFFER_LARGEST_ARB: - FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value); - break; - - case WGL_TEXTURE_FORMAT_ARB: - switch (value) - { - case WGL_TEXTURE_RGBA_ARB: - TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n"); - internalFormat = GL_RGBA; - break; - case WGL_TEXTURE_RGB_ARB: - TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n"); - internalFormat = GL_RGB; - break; - case WGL_NO_TEXTURE_ARB: - TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n"); - internalFormat = 0; - break; - default: - WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - goto done; - } - break; - - case WGL_TEXTURE_TARGET_ARB: - pbuffer->face = 0; - switch (value) - { - case WGL_NO_TEXTURE_ARB: - TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n"); - target = 0; - break; - case WGL_TEXTURE_CUBE_MAP_ARB: - TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n"); - target = GL_TEXTURE_CUBE_MAP; - pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - break; - case WGL_TEXTURE_1D_ARB: - FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n"); - RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); - goto done; - case WGL_TEXTURE_2D_ARB: - TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n"); - target = GL_TEXTURE_2D; - break; - case WGL_TEXTURE_RECTANGLE_NV: - TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n"); - target = GL_TEXTURE_RECTANGLE; - break; - default: - WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - goto done; - } - break; - - case WGL_MIPMAP_TEXTURE_ARB: - TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value); - pbuffer->max_level = 0; - if (value) - { - int size = min(iWidth, iHeight) / 2; - while (size) - { - pbuffer->max_level++; - size /= 2; - } - } - break; - - default: - WARN("unknown attribute 0x%x\n", attr); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - goto done; - } - } + TRACE("hdc %p, format %d, largest %u, texture_format %#x, texture_target %#x, max_level %#x, width %d, height %d, private %p\n", + hdc, format, largest, texture_format, texture_target, max_level, *width, *height, private);
- if (!target || !internalFormat) + if (!texture_target || !texture_format) { - pbuffer->no_texture = TRUE; /* no actual way to turn off ability to texture; use most permissive target */ - target = GL_TEXTURE_RECTANGLE; - internalFormat = GL_RGB; + texture_target = GL_TEXTURE_RECTANGLE; + texture_format = GL_RGB; }
- err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer); + err = CGLCreatePBuffer(*width, *height, texture_target, texture_format, max_level, (CGLPBufferObj *)private); if (err != kCGLNoError) { WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err)); - pbuffer->pbuffer = NULL; - if (err == kCGLBadAlloc) - RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); - else - RtlSetLastWin32Error(ERROR_INVALID_DATA); - } - -done: - if (!pbuffer->pbuffer) - { - free(pbuffer); - return NULL; + return FALSE; }
- TRACE(" -> %p\n", pbuffer); - return pbuffer; -} - + pthread_mutex_lock(&dc_pbuffers_mutex); + CFDictionarySetValue(dc_pbuffers, hdc, private); + pthread_mutex_unlock(&dc_pbuffers_mutex);
-/********************************************************************** - * macdrv_wglDestroyPbufferARB - * - * WGL_ARB_pbuffer: wglDestroyPbufferARB - */ -static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer) -{ - TRACE("pbuffer %p\n", pbuffer); - if (pbuffer && pbuffer->pbuffer) - CGLReleasePBuffer(pbuffer->pbuffer); - free(pbuffer); - return GL_TRUE; + TRACE(" -> %p\n", *private); + return TRUE; }
- -/********************************************************************** - * macdrv_wglGetPbufferDCARB - * - * WGL_ARB_pbuffer: wglGetPbufferDCARB - */ -static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer) +static BOOL macdrv_pbuffer_destroy(HDC hdc, void *private) { - HDC hdc; - struct wgl_pbuffer *prev; - - hdc = NtGdiOpenDCW(NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL); - if (!hdc) return 0; + TRACE("private %p\n", private);
pthread_mutex_lock(&dc_pbuffers_mutex); - prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc); - if (prev) - { - CGLReleasePBuffer(prev->pbuffer); - free(prev); - } - CFDictionarySetValue(dc_pbuffers, hdc, pbuffer); + CFDictionaryRemoveValue(dc_pbuffers, hdc); pthread_mutex_unlock(&dc_pbuffers_mutex);
- NtGdiSetPixelFormat(hdc, pbuffer->format); - TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc); - return hdc; + CGLReleasePBuffer(private); + return GL_TRUE; }
@@ -2744,15 +2542,16 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w } else { - struct wgl_pbuffer *pbuffer; + CGLPBufferObj pbuffer;
pthread_mutex_lock(&dc_pbuffers_mutex); - pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc); + pbuffer = (CGLPBufferObj)CFDictionaryGetValue(dc_pbuffers, draw_hdc); if (pbuffer) { - if (context->format != pbuffer->format) + int format = opengl_funcs.p_wglGetPixelFormat(draw_hdc); + if (context->format != format) { - WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format); + WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, format, context, context->format); pthread_mutex_unlock(&dc_pbuffers_mutex); RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT); return FALSE; @@ -2795,7 +2594,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w else { pthread_mutex_lock(&dc_pbuffers_mutex); - context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc); + context->read_pbuffer = (CGLPBufferObj)CFDictionaryGetValue(dc_pbuffers, read_hdc); pthread_mutex_unlock(&dc_pbuffers_mutex); } } @@ -2930,113 +2729,6 @@ static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute) }
-/********************************************************************** - * macdrv_wglQueryPbufferARB - * - * WGL_ARB_pbuffer: wglQueryPbufferARB - */ -static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue) -{ - CGLError err; - GLsizei width; - GLsizei height; - GLenum target; - GLenum internalFormat; - GLint mipmap; - - TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue); - - err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap); - if (err != kCGLNoError) - { - WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err)); - RtlSetLastWin32Error(ERROR_INVALID_HANDLE); - return GL_FALSE; - } - - switch (iAttribute) - { - case WGL_PBUFFER_WIDTH_ARB: - *piValue = width; - break; - case WGL_PBUFFER_HEIGHT_ARB: - *piValue = height; - break; - case WGL_PBUFFER_LOST_ARB: - /* Mac PBuffers can't be lost */ - *piValue = GL_FALSE; - break; - case WGL_TEXTURE_FORMAT_ARB: - if (pbuffer->no_texture) - *piValue = WGL_NO_TEXTURE_ARB; - else switch (internalFormat) - { - case GL_RGBA: - *piValue = WGL_TEXTURE_RGBA_ARB; - break; - case GL_RGB: - default: - *piValue = WGL_TEXTURE_RGB_ARB; - break; - } - break; - case WGL_TEXTURE_TARGET_ARB: - if (pbuffer->no_texture) - *piValue = WGL_NO_TEXTURE_ARB; - else switch (target) - { - case GL_TEXTURE_CUBE_MAP: - *piValue = WGL_TEXTURE_CUBE_MAP_ARB; - break; - case GL_TEXTURE_2D: - *piValue = WGL_TEXTURE_2D_ARB; - break; - case GL_TEXTURE_RECTANGLE: - default: - *piValue = WGL_TEXTURE_RECTANGLE_NV; - break; - } - break; - case WGL_MIPMAP_TEXTURE_ARB: - *piValue = (pbuffer->max_level > 0); - break; - case WGL_MIPMAP_LEVEL_ARB: - *piValue = pbuffer->level; - break; - case WGL_CUBE_MAP_FACE_ARB: - switch (pbuffer->face) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - default: - *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; - break; - } - break; - default: - WARN("invalid attribute 0x%x\n", iAttribute); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - return GL_FALSE; - } - - return GL_TRUE; -} - - /********************************************************************** * macdrv_wglQueryRendererIntegerWINE * @@ -3130,129 +2822,19 @@ done: }
-/********************************************************************** - * macdrv_wglReleasePbufferDCARB - * - * WGL_ARB_pbuffer: wglReleasePbufferDCARB - */ -static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc) -{ - struct wgl_pbuffer *prev; - - TRACE("pbuffer %p hdc %p\n", pbuffer, hdc); - - pthread_mutex_lock(&dc_pbuffers_mutex); - - prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc); - if (prev) - { - if (prev != pbuffer) - FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer); - CGLReleasePBuffer(prev->pbuffer); - free(prev); - CFDictionaryRemoveValue(dc_pbuffers, hdc); - } - else hdc = 0; - - pthread_mutex_unlock(&dc_pbuffers_mutex); - - return hdc && NtGdiDeleteObjectApp(hdc); -} - - -/********************************************************************** - * macdrv_wglReleaseTexImageARB - * - * WGL_ARB_render_texture: wglReleaseTexImageARB - */ -static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer) -{ - struct wgl_context *context = NtCurrentTeb()->glContext; - CGLError err; - - TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer); - - if (pbuffer->no_texture) - { - RtlSetLastWin32Error(ERROR_INVALID_OPERATION); - return GL_FALSE; - } - - err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE); - if (err != kCGLNoError) - { - WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err)); - RtlSetLastWin32Error(ERROR_INVALID_OPERATION); - return GL_FALSE; - } - - return GL_TRUE; -} - - -/********************************************************************** - * macdrv_wglSetPbufferAttribARB - * - * WGL_ARB_render_texture: wglSetPbufferAttribARB - */ -static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList) +static BOOL macdrv_pbuffer_updated(HDC hdc, void *private, GLenum cube_face, GLint mipmap_level) { struct wgl_context *context = NtCurrentTeb()->glContext; + CGLPBufferObj pbuffer = private;
- TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList); - - for ( ; piAttribList && *piAttribList; piAttribList += 2) - { - int attr = piAttribList[0]; - int value = piAttribList[1]; - switch (attr) - { - case WGL_MIPMAP_LEVEL_ARB: - TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value); - pbuffer->level = value; - break; - case WGL_CUBE_MAP_FACE_ARB: - switch (value) - { - case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n"); - pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - break; - case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n"); - pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; - break; - case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n"); - pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; - break; - case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n"); - pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; - break; - case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n"); - pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; - break; - case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n"); - pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; - break; - default: - WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - return GL_FALSE; - } - break; - default: - WARN("invalid attribute 0x%x\n", attr); - RtlSetLastWin32Error(ERROR_INVALID_DATA); - return GL_FALSE; - } - } + TRACE("hdc %p pbuffer %p cube_face %#x mipmap_level %d\n", hdc, pbuffer, cube_face, mipmap_level);
if (context && context->draw_pbuffer == pbuffer) + { + context->draw_pbuffer_face = cube_face; + context->draw_pbuffer_level = mipmap_level; make_context_current(context, FALSE); + }
return GL_TRUE; } @@ -3351,18 +2933,6 @@ static const char *macdrv_init_wgl_extensions(void)
if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions)) { - register_extension("WGL_ARB_pbuffer"); - opengl_funcs.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB; - opengl_funcs.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB; - opengl_funcs.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB; - opengl_funcs.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB; - opengl_funcs.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB; - - register_extension("WGL_ARB_render_texture"); - opengl_funcs.p_wglBindTexImageARB = macdrv_wglBindTexImageARB; - opengl_funcs.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB; - opengl_funcs.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB; - if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) || gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions)) register_extension("WGL_NV_render_texture_rectangle"); @@ -3758,10 +3328,10 @@ static BOOL macdrv_wglSwapBuffers(HDC hdc) } else { - struct wgl_pbuffer *pbuffer; + CGLPBufferObj pbuffer;
pthread_mutex_lock(&dc_pbuffers_mutex); - pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc); + pbuffer = (CGLPBufferObj)CFDictionaryGetValue(dc_pbuffers, hdc); pthread_mutex_unlock(&dc_pbuffers_mutex);
if (!pbuffer) @@ -3796,6 +3366,10 @@ static const struct opengl_driver_funcs macdrv_driver_funcs = .p_describe_pixel_format = macdrv_describe_pixel_format, .p_init_wgl_extensions = macdrv_init_wgl_extensions, .p_set_pixel_format = macdrv_set_pixel_format, + .p_pbuffer_create = macdrv_pbuffer_create, + .p_pbuffer_destroy = macdrv_pbuffer_destroy, + .p_pbuffer_updated = macdrv_pbuffer_updated, + .p_pbuffer_bind = macdrv_pbuffer_bind, };
static struct opengl_funcs opengl_funcs = diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index cb15846ae53..cc595f87252 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -663,11 +663,13 @@ static BOOL wayland_wglSwapIntervalEXT(int interval) return ret; }
-static BOOL wayland_pbuffer_create(HDC hdc, int format, BOOL largest, int *width, int *height, void **private) +static BOOL wayland_pbuffer_create(HDC hdc, int format, BOOL largest, GLenum texture_format, GLenum texture_target, + GLint max_level, GLsizei *width, GLsizei *height, void **private) { struct wayland_gl_drawable *drawable;
- TRACE("hdc %p, format %d, largest %u, width %d, height %d, private %p\n", hdc, format, largest, *width, *height, private); + TRACE("hdc %p, format %d, largest %u, texture_format %#x, texture_target %#x, max_level %#x, width %d, height %d, private %p\n", + hdc, format, largest, texture_format, texture_target, max_level, *width, *height, private);
/* Use an unmapped wayland surface as our offscreen "pbuffer" surface. */ if (!(drawable = wayland_gl_drawable_create(0, hdc, format, *width, *height))) return FALSE; @@ -695,6 +697,18 @@ static BOOL wayland_pbuffer_destroy(HDC hdc, void *private) return GL_TRUE; }
+static BOOL wayland_pbuffer_updated(HDC hdc, void *private, GLenum cube_face, GLint mipmap_level) +{ + TRACE("hdc %p, private %p, cube_face %#x, mipmap_level %d\n", hdc, private, cube_face, mipmap_level); + return GL_TRUE; +} + +static UINT wayland_pbuffer_bind(HDC hdc, void *private, GLenum buffer) +{ + TRACE("hdc %p, private %p, buffer %#x\n", hdc, private, buffer); + return -1; /* use default implementation */ +} + static BOOL describe_pixel_format(EGLConfig config, struct wgl_pixel_format *fmt, BOOL pbuffer_single) { EGLint value, surface_type; @@ -960,6 +974,8 @@ static const struct opengl_driver_funcs wayland_driver_funcs = .p_set_pixel_format = wayland_set_pixel_format, .p_pbuffer_create = wayland_pbuffer_create, .p_pbuffer_destroy = wayland_pbuffer_destroy, + .p_pbuffer_updated = wayland_pbuffer_updated, + .p_pbuffer_bind = wayland_pbuffer_bind, };
/********************************************************************** diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 5b100659630..05ae284761c 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1940,14 +1940,16 @@ static struct wgl_context *X11DRV_wglCreateContextAttribsARB( HDC hdc, struct wg return ret; }
-static BOOL x11drv_pbuffer_create( HDC hdc, int format, BOOL largest, int *width, int *height, void **private ) +static BOOL x11drv_pbuffer_create( HDC hdc, int format, BOOL largest, GLenum texture_format, GLenum texture_target, + GLint max_level, GLsizei *width, GLsizei *height, void **private ) { const struct glx_pixel_format *fmt; int glx_attribs[7], count = 0; struct gl_drawable *surface; RECT rect;
- TRACE( "hdc %p, format %d, largest %u, width %d, height %d, private %p\n", hdc, format, largest, *width, *height, private ); + TRACE( "hdc %p, format %d, largest %u, texture_format %#x, texture_target %#x, max_level %#x, width %d, height %d, private %p\n", + hdc, format, largest, texture_format, texture_target, max_level, *width, *height, private );
/* Convert the WGL pixelformat to a GLX format, if it fails then the format is invalid */ if (!(fmt = get_pixel_format( gdi_display, format, TRUE /* Offscreen */ ))) @@ -2006,6 +2008,18 @@ static BOOL x11drv_pbuffer_destroy( HDC hdc, void *private ) return GL_TRUE; }
+static BOOL x11drv_pbuffer_updated( HDC hdc, void *private, GLenum cube_face, GLint mipmap_level ) +{ + TRACE( "hdc %p, private %p, cube_face %#x, mipmap_level %d\n", hdc, private, cube_face, mipmap_level ); + return GL_TRUE; +} + +static UINT x11drv_pbuffer_bind( HDC hdc, void *private, GLenum buffer ) +{ + TRACE( "hdc %p, private %p, buffer %#x\n", hdc, private, buffer ); + return -1; /* use default implementation */ +} + /** * X11DRV_wglGetSwapIntervalEXT * @@ -2301,6 +2315,8 @@ static const struct opengl_driver_funcs x11drv_driver_funcs = .p_set_pixel_format = x11drv_set_pixel_format, .p_pbuffer_create = x11drv_pbuffer_create, .p_pbuffer_destroy = x11drv_pbuffer_destroy, + .p_pbuffer_updated = x11drv_pbuffer_updated, + .p_pbuffer_bind = x11drv_pbuffer_bind, };
static struct opengl_funcs opengl_funcs = diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 11bcbe6758a..1d78ac09b1c 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -118,8 +118,10 @@ struct opengl_driver_funcs const char *(*p_init_wgl_extensions)(void); BOOL (*p_set_pixel_format)(HWND,int,int,BOOL);
- BOOL (*p_pbuffer_create)(HDC,int,BOOL,GLsizei*,GLsizei*,void **); + BOOL (*p_pbuffer_create)(HDC,int,BOOL,GLenum,GLenum,GLint,GLsizei*,GLsizei*,void **); BOOL (*p_pbuffer_destroy)(HDC,void*); + BOOL (*p_pbuffer_updated)(HDC,void*,GLenum,GLint); + UINT (*p_pbuffer_bind)(HDC,void*,GLenum); };
#endif /* WINE_UNIX_LIB */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 50 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 941a5e5de22..93a9a5f4d58 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -422,12 +422,37 @@ static BOOL nulldrv_set_pixel_format( HWND hwnd, int old_format, int new_format, return TRUE; }
+static BOOL nulldrv_pbuffer_create( HDC hdc, int format, BOOL largest, GLenum texture_format, GLenum texture_target, + GLint max_level, GLsizei *width, GLsizei *height, void **private ) +{ + return FALSE; +} + +static BOOL nulldrv_pbuffer_destroy( HDC hdc, void *private ) +{ + return FALSE; +} + +static BOOL nulldrv_pbuffer_updated( HDC hdc, void *private, GLenum cube_face, GLint mipmap_level ) +{ + return GL_TRUE; +} + +static UINT nulldrv_pbuffer_bind( HDC hdc, void *private, GLenum buffer ) +{ + return -1; /* use default implementation */ +} + static const struct opengl_driver_funcs nulldrv_funcs = { .p_init_pixel_formats = nulldrv_init_pixel_formats, .p_describe_pixel_format = nulldrv_describe_pixel_format, .p_init_wgl_extensions = nulldrv_init_wgl_extensions, .p_set_pixel_format = nulldrv_set_pixel_format, + .p_pbuffer_create = nulldrv_pbuffer_create, + .p_pbuffer_destroy = nulldrv_pbuffer_destroy, + .p_pbuffer_updated = nulldrv_pbuffer_updated, + .p_pbuffer_bind = nulldrv_pbuffer_bind, }; static const struct opengl_driver_funcs *driver_funcs = &nulldrv_funcs; static UINT formats_count, onscreen_count; @@ -987,20 +1012,17 @@ static void display_funcs_init(void) display_funcs->p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */ display_funcs->p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
- if (driver_funcs->p_pbuffer_create) - { - register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_pbuffer" ); - display_funcs->p_wglCreatePbufferARB = win32u_wglCreatePbufferARB; - display_funcs->p_wglDestroyPbufferARB = win32u_wglDestroyPbufferARB; - display_funcs->p_wglGetPbufferDCARB = win32u_wglGetPbufferDCARB; - display_funcs->p_wglReleasePbufferDCARB = win32u_wglReleasePbufferDCARB; - display_funcs->p_wglQueryPbufferARB = win32u_wglQueryPbufferARB; - - register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_render_texture" ); - display_funcs->p_wglBindTexImageARB = win32u_wglBindTexImageARB; - display_funcs->p_wglReleaseTexImageARB = win32u_wglReleaseTexImageARB; - display_funcs->p_wglSetPbufferAttribARB = win32u_wglSetPbufferAttribARB; - } + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_pbuffer" ); + display_funcs->p_wglCreatePbufferARB = win32u_wglCreatePbufferARB; + display_funcs->p_wglDestroyPbufferARB = win32u_wglDestroyPbufferARB; + display_funcs->p_wglGetPbufferDCARB = win32u_wglGetPbufferDCARB; + display_funcs->p_wglReleasePbufferDCARB = win32u_wglReleasePbufferDCARB; + display_funcs->p_wglQueryPbufferARB = win32u_wglQueryPbufferARB; + + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_render_texture" ); + display_funcs->p_wglBindTexImageARB = win32u_wglBindTexImageARB; + display_funcs->p_wglReleaseTexImageARB = win32u_wglReleaseTexImageARB; + display_funcs->p_wglSetPbufferAttribARB = win32u_wglSetPbufferAttribARB; }
static struct opengl_funcs *get_dc_funcs( HDC hdc, void *null_funcs )
On Mon Apr 7 13:21:43 2025 +0000, Aida Jonikienė wrote:
This doesn't include tests for wglBindTexImageARB() (which is a very important function for the TLOPO game since commit 272c55ac257315ef8393df357a79aac4e0d6cd76)
The function was already implemented without tests.
On Mon Apr 7 13:37:22 2025 +0000, Rémi Bernon wrote:
The function was already implemented without tests.
But it has a bug that causes the 3D viewport in that game to be black (so poking at the function with some tests could be nice in ensuring that function works like native)
On Mon Apr 7 13:37:22 2025 +0000, Aida Jonikienė wrote:
But it has a bug that causes the 3D viewport in that game to be black (so poking at the function with some tests could be nice in ensuring that function works like native)
This MR is not meant to fix any of the functions in a significant way, this would need to be done separately.