winex11.drv: Prioritize smaller depth formats when zero depth is requested in X11DRV_wglChoosePixelFormatARB().
Fixes Ancient Cities' black screen on Nvidia. Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bfa3c95611
commit
e392e0ac28
|
@ -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))))
|
||||
{
|
||||
for (it = 0; it < nCfgs && pfmt_it < nMaxFormats; ++it)
|
||||
{
|
||||
if (pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id))
|
||||
{
|
||||
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 = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
ERR("No memory.\n");
|
||||
XFree(cfgs);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
*nNumFormats = pfmt_it;
|
||||
/** free list */
|
||||
format_count = 0;
|
||||
for (it = 0; it < nCfgs; ++it)
|
||||
{
|
||||
struct choose_pixel_format_arb_format *format;
|
||||
|
||||
if (pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id))
|
||||
{
|
||||
ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_pixel_formats; ++i)
|
||||
if (pixel_formats[i].fmt_id == fmt_id)
|
||||
break;
|
||||
|
||||
if (i == nb_pixel_formats)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue