Commit e392e0ac authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

winex11.drv: Prioritize smaller depth formats when zero depth is requested in…

winex11.drv: Prioritize smaller depth formats when zero depth is requested in X11DRV_wglChoosePixelFormatARB(). Fixes Ancient Cities' black screen on Nvidia. Signed-off-by: 's avatarPaul Gofman <pgofman@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent bfa3c956
...@@ -1764,6 +1764,62 @@ static void test_swap_control(HDC oldhdc) ...@@ -1764,6 +1764,62 @@ static void test_swap_control(HDC oldhdc)
wglMakeCurrent(oldhdc, oldctx); wglMakeCurrent(oldhdc, oldctx);
} }
static void test_wglChoosePixelFormatARB(HDC hdc)
{
static int attrib_list[] =
{
WGL_DRAW_TO_WINDOW_ARB, 1,
WGL_SUPPORT_OPENGL_ARB, 1,
0
};
PIXELFORMATDESCRIPTOR fmt, last_fmt;
BYTE depth, last_depth;
UINT format_count;
int formats[1024];
unsigned int i;
int res;
if (!pwglChoosePixelFormatARB)
{
skip("wglChoosePixelFormatARB is not available\n");
return;
}
format_count = 0;
res = pwglChoosePixelFormatARB(hdc, attrib_list, NULL, ARRAY_SIZE(formats), formats, &format_count);
ok(res, "Got unexpected result %d.\n", res);
memset(&last_fmt, 0, sizeof(last_fmt));
last_depth = 0;
for (i = 0; i < format_count; ++i)
{
memset(&fmt, 0, sizeof(fmt));
if (!DescribePixelFormat(hdc, formats[i], sizeof(fmt), &fmt)
|| (fmt.dwFlags & PFD_GENERIC_FORMAT))
{
memset(&fmt, 0, sizeof(fmt));
continue;
}
depth = fmt.cDepthBits;
fmt.cDepthBits = 0;
fmt.cStencilBits = 0;
if (memcmp(&fmt, &last_fmt, sizeof(fmt)))
{
last_fmt = fmt;
last_depth = depth;
}
else
{
ok(last_depth <= depth, "Got unexpected depth %u, last_depth %u, i %u, format %u.\n",
depth, last_depth, i, formats[i]);
}
}
}
START_TEST(opengl) START_TEST(opengl)
{ {
HWND hwnd; HWND hwnd;
...@@ -1858,6 +1914,7 @@ START_TEST(opengl) ...@@ -1858,6 +1914,7 @@ START_TEST(opengl)
} }
test_choosepixelformat(); test_choosepixelformat();
test_wglChoosePixelFormatARB(hdc);
test_debug_message_callback(); test_debug_message_callback();
test_setpixelformat(hdc); test_setpixelformat(hdc);
test_destroy(hdc); test_destroy(hdc);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "x11drv.h" #include "x11drv.h"
#include "xcomposite.h" #include "xcomposite.h"
#include "winternl.h" #include "winternl.h"
#include "wine/heap.h"
#include "wine/debug.h" #include "wine/debug.h"
#ifdef SONAME_LIBGL #ifdef SONAME_LIBGL
...@@ -2486,6 +2487,37 @@ static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int ...@@ -2486,6 +2487,37 @@ static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int
return ret; return ret;
} }
struct choose_pixel_format_arb_format
{
int format;
int original_index;
PIXELFORMATDESCRIPTOR pfd;
int depth, stencil;
};
static int compare_formats(const void *a, const void *b)
{
/* Order formats so that onscreen formats go first. Then, if no depth bits requested,
* prioritize formats with smaller depth within the original sort order with respect to
* other attributes. */
const struct choose_pixel_format_arb_format *fmt_a = a, *fmt_b = b;
BOOL offscreen_a, offscreen_b;
offscreen_a = fmt_a->format > nb_onscreen_formats;
offscreen_b = fmt_b->format > nb_onscreen_formats;
if (offscreen_a != offscreen_b)
return offscreen_a - offscreen_b;
if (memcmp(&fmt_a->pfd, &fmt_b->pfd, sizeof(fmt_a->pfd)))
return fmt_a->original_index - fmt_b->original_index;
if (fmt_a->depth != fmt_b->depth)
return fmt_a->depth - fmt_b->depth;
if (fmt_a->stencil != fmt_b->stencil)
return fmt_a->stencil - fmt_b->stencil;
return fmt_a->original_index - fmt_b->original_index;
}
/** /**
* X11DRV_wglChoosePixelFormatARB * X11DRV_wglChoosePixelFormatARB
* *
...@@ -2494,17 +2526,15 @@ static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int ...@@ -2494,17 +2526,15 @@ static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int
static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList,
UINT nMaxFormats, int *piFormats, UINT *nNumFormats ) UINT nMaxFormats, int *piFormats, UINT *nNumFormats )
{ {
struct choose_pixel_format_arb_format *formats;
int it, i, format_count;
BYTE depth_bits = 0;
GLXFBConfig* cfgs;
DWORD dwFlags = 0;
int attribs[256]; int attribs[256];
int nAttribs = 0; int nAttribs = 0;
GLXFBConfig* cfgs;
int nCfgs = 0; int nCfgs = 0;
int it;
int fmt_id; int fmt_id;
int start, end;
UINT pfmt_it = 0;
int run;
int i;
DWORD dwFlags = 0;
TRACE("(%p, %p, %p, %d, %p, %p): hackish\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); TRACE("(%p, %p, %p, %d, %p, %p): hackish\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
if (NULL != pfAttribFList) { if (NULL != pfAttribFList) {
...@@ -2548,6 +2578,10 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c ...@@ -2548,6 +2578,10 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
if(piAttribIList[i+1]) if(piAttribIList[i+1])
dwFlags |= PFD_SUPPORT_GDI; dwFlags |= PFD_SUPPORT_GDI;
break; break;
case WGL_DEPTH_BITS_ARB:
depth_bits = piAttribIList[i+1];
break;
} }
} }
...@@ -2558,37 +2592,57 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c ...@@ -2558,37 +2592,57 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
return GL_FALSE; return GL_FALSE;
} }
/* Loop through all matching formats and check if they are suitable. if (!(formats = heap_alloc(nCfgs * sizeof(*formats))))
* Note that this function should at max return nMaxFormats different formats */ {
for(run=0; run < 2; run++) ERR("No memory.\n");
XFree(cfgs);
return GL_FALSE;
}
format_count = 0;
for (it = 0; it < nCfgs; ++it)
{ {
for (it = 0; it < nCfgs && pfmt_it < nMaxFormats; ++it) struct choose_pixel_format_arb_format *format;
if (pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id))
{ {
if (pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id)) ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
{ continue;
ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); }
continue;
}
/* During the first run we only want onscreen formats and during the second only offscreen */ for (i = 0; i < nb_pixel_formats; ++i)
start = run == 1 ? nb_onscreen_formats : 0; if (pixel_formats[i].fmt_id == fmt_id)
end = run == 1 ? nb_pixel_formats : nb_onscreen_formats; break;
for (i = start; i < end; i++) if (i == nb_pixel_formats)
{ continue;
if (pixel_formats[i].fmt_id == fmt_id && (pixel_formats[i].dwFlags & dwFlags) == dwFlags)
{ format = &formats[format_count];
piFormats[pfmt_it++] = i + 1; format->format = i + 1;
TRACE("at %d/%d found FBCONFIG_ID 0x%x (%d)\n", format->original_index = it;
it + 1, nCfgs, fmt_id, i + 1);
break; memset(&format->pfd, 0, sizeof(format->pfd));
} if (!describe_pixel_format(format->format, &format->pfd, TRUE))
} ERR("describe_pixel_format failed, format %d.\n", format->format);
format->depth = format->pfd.cDepthBits;
format->stencil = format->pfd.cStencilBits;
if (!depth_bits && !(format->pfd.dwFlags & PFD_GENERIC_FORMAT))
{
format->pfd.cDepthBits = 0;
format->pfd.cStencilBits = 0;
} }
++format_count;
} }
*nNumFormats = pfmt_it; qsort(formats, format_count, sizeof(*formats), compare_formats);
/** free list */
*nNumFormats = min(nMaxFormats, format_count);
for (i = 0; i < *nNumFormats; ++i)
piFormats[i] = formats[i].format;
heap_free(formats);
XFree(cfgs); XFree(cfgs);
return GL_TRUE; return GL_TRUE;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment