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)
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)
{
HWND hwnd;
......@@ -1858,6 +1914,7 @@ START_TEST(opengl)
}
test_choosepixelformat();
test_wglChoosePixelFormatARB(hdc);
test_debug_message_callback();
test_setpixelformat(hdc);
test_destroy(hdc);
......
......@@ -40,6 +40,7 @@
#include "x11drv.h"
#include "xcomposite.h"
#include "winternl.h"
#include "wine/heap.h"
#include "wine/debug.h"
#ifdef SONAME_LIBGL
......@@ -2486,6 +2487,37 @@ static BOOL X11DRV_wglSetPbufferAttribARB( struct wgl_pbuffer *object, const int
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
*
......@@ -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,
UINT nMaxFormats, int *piFormats, UINT *nNumFormats )
{
struct choose_pixel_format_arb_format *formats;
int it, i, format_count;
BYTE depth_bits = 0;
GLXFBConfig* cfgs;
DWORD dwFlags = 0;
int attribs[256];
int nAttribs = 0;
GLXFBConfig* cfgs;
int nCfgs = 0;
int it;
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);
if (NULL != pfAttribFList) {
......@@ -2548,6 +2578,10 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
if(piAttribIList[i+1])
dwFlags |= PFD_SUPPORT_GDI;
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
return GL_FALSE;
}
/* Loop through all matching formats and check if they are suitable.
* Note that this function should at max return nMaxFormats different formats */
for(run=0; run < 2; run++)
if (!(formats = heap_alloc(nCfgs * sizeof(*formats))))
{
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 */
start = run == 1 ? nb_onscreen_formats : 0;
end = run == 1 ? nb_pixel_formats : nb_onscreen_formats;
for (i = 0; i < nb_pixel_formats; ++i)
if (pixel_formats[i].fmt_id == fmt_id)
break;
for (i = start; i < end; i++)
{
if (pixel_formats[i].fmt_id == fmt_id && (pixel_formats[i].dwFlags & dwFlags) == dwFlags)
{
piFormats[pfmt_it++] = i + 1;
TRACE("at %d/%d found FBCONFIG_ID 0x%x (%d)\n",
it + 1, nCfgs, fmt_id, i + 1);
break;
}
}
if (i == nb_pixel_formats)
continue;
format = &formats[format_count];
format->format = i + 1;
format->original_index = it;
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;
/** free list */
qsort(formats, format_count, sizeof(*formats), compare_formats);
*nNumFormats = min(nMaxFormats, format_count);
for (i = 0; i < *nNumFormats; ++i)
piFormats[i] = formats[i].format;
heap_free(formats);
XFree(cfgs);
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