wined3d: Simplify context_choose_pixel_format().

Simply rank the formats instead of doing multiple passes over the list.
This commit is contained in:
Henri Verbeet 2011-11-08 20:48:57 +01:00 committed by Alexandre Julliard
parent 0ba5f7dd98
commit 81ae0cea7c
3 changed files with 49 additions and 122 deletions

View File

@ -1124,33 +1124,9 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
BOOL auxBuffers, BOOL findCompatible) BOOL auxBuffers, BOOL findCompatible)
{ {
int iPixelFormat=0; int iPixelFormat=0;
unsigned int matchtry;
BYTE redBits, greenBits, blueBits, alphaBits, colorBits; BYTE redBits, greenBits, blueBits, alphaBits, colorBits;
BYTE depthBits=0, stencilBits=0; BYTE depthBits=0, stencilBits=0;
unsigned int current_value;
static const struct
{
BOOL require_aux;
BOOL exact_alpha;
BOOL exact_color;
}
matches[] =
{
/* First, try without alpha match buffers. MacOS supports aux buffers only
* on A8R8G8B8, and we prefer better offscreen rendering over an alpha match.
* Then try without aux buffers - this is the most common cause for not
* finding a pixel format. Also some drivers(the open source ones)
* only offer 32 bit ARB pixel formats. First try without an exact alpha
* match, then try without an exact alpha and color match.
*/
{ TRUE, TRUE, TRUE },
{ TRUE, FALSE, TRUE },
{ FALSE, TRUE, TRUE },
{ FALSE, FALSE, TRUE },
{ TRUE, FALSE, FALSE },
{ FALSE, FALSE, FALSE },
};
unsigned int cfg_count = device->adapter->cfg_count; unsigned int cfg_count = device->adapter->cfg_count;
unsigned int i; unsigned int i;
@ -1167,84 +1143,56 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
getDepthStencilBits(ds_format, &depthBits, &stencilBits); getDepthStencilBits(ds_format, &depthBits, &stencilBits);
for (matchtry = 0; matchtry < (sizeof(matches) / sizeof(*matches)) && !iPixelFormat; ++matchtry) current_value = 0;
for (i = 0; i < cfg_count; ++i)
{ {
for (i = 0; i < cfg_count; ++i) const struct wined3d_pixel_format *cfg = &device->adapter->cfgs[i];
unsigned int value;
/* For now only accept RGBA formats. Perhaps some day we will
* allow floating point formats for pbuffers. */
if (cfg->iPixelType != WGL_TYPE_RGBA_ARB)
continue;
/* In window mode we need a window drawable format and double buffering. */
if (!(cfg->windowDrawable && cfg->doubleBuffer))
continue;
if (cfg->redSize < redBits)
continue;
if (cfg->greenSize < greenBits)
continue;
if (cfg->blueSize < blueBits)
continue;
if (cfg->alphaSize < alphaBits)
continue;
if (cfg->depthSize < depthBits)
continue;
if (stencilBits && cfg->stencilSize != stencilBits)
continue;
/* Check multisampling support. */
if (cfg->numSamples)
continue;
value = 1;
/* We try to locate a format which matches our requirements exactly. In case of
* depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */
if (cfg->depthSize == depthBits)
value += 1;
if (cfg->stencilSize == stencilBits)
value += 2;
if (cfg->alphaSize == alphaBits)
value += 4;
/* We like to have aux buffers in backbuffer mode */
if (auxBuffers && cfg->auxBuffers)
value += 8;
if (cfg->redSize == redBits
&& cfg->greenSize == greenBits
&& cfg->blueSize == blueBits)
value += 16;
if (value > current_value)
{ {
const struct wined3d_pixel_format *cfg = &device->adapter->cfgs[i]; iPixelFormat = cfg->iPixelFormat;
BOOL exactDepthMatch = TRUE; current_value = value;
/* For now only accept RGBA formats. Perhaps some day we will
* allow floating point formats for pbuffers. */
if(cfg->iPixelType != WGL_TYPE_RGBA_ARB)
continue;
/* In window mode we need a window drawable format and double buffering. */
if(!(cfg->windowDrawable && cfg->doubleBuffer))
continue;
/* We like to have aux buffers in backbuffer mode */
if(auxBuffers && !cfg->auxBuffers && matches[matchtry].require_aux)
continue;
if(matches[matchtry].exact_color) {
if(cfg->redSize != redBits)
continue;
if(cfg->greenSize != greenBits)
continue;
if(cfg->blueSize != blueBits)
continue;
} else {
if(cfg->redSize < redBits)
continue;
if(cfg->greenSize < greenBits)
continue;
if(cfg->blueSize < blueBits)
continue;
}
if(matches[matchtry].exact_alpha) {
if(cfg->alphaSize != alphaBits)
continue;
} else {
if(cfg->alphaSize < alphaBits)
continue;
}
/* We try to locate a format which matches our requirements exactly. In case of
* depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */
if(cfg->depthSize < depthBits)
continue;
else if(cfg->depthSize > depthBits)
exactDepthMatch = FALSE;
/* In all cases make sure the number of stencil bits matches our requirements
* even when we don't need stencil because it could affect performance EXCEPT
* on cards which don't offer depth formats without stencil like the i915 drivers
* on Linux. */
if (stencilBits != cfg->stencilSize
&& !(device->adapter->brokenStencil && stencilBits <= cfg->stencilSize))
continue;
/* Check multisampling support */
if (cfg->numSamples)
continue;
/* When we have passed all the checks then we have found a format which matches our
* requirements. Note that we only check for a limit number of capabilities right now,
* so there can easily be a dozen of pixel formats which appear to be the 'same' but
* can still differ in things like multisampling, stereo, SRGB and other flags.
*/
/* Exit the loop as we have found a format :) */
if(exactDepthMatch) {
iPixelFormat = cfg->iPixelFormat;
break;
} else if(!iPixelFormat) {
/* In the end we might end up with a format which doesn't exactly match our depth
* requirements. Accept the first format we found because formats with higher iPixelFormat
* values tend to have more extended capabilities (e.g. multisampling) which we don't need. */
iPixelFormat = cfg->iPixelFormat;
}
} }
} }

View File

@ -5260,7 +5260,6 @@ static BOOL InitAdapters(struct wined3d *wined3d)
struct wined3d_pixel_format *cfgs; struct wined3d_pixel_format *cfgs;
int iPixelFormat; int iPixelFormat;
int res; int res;
int i;
DISPLAY_DEVICEW DisplayDevice; DISPLAY_DEVICEW DisplayDevice;
HDC hdc; HDC hdc;
@ -5439,25 +5438,6 @@ static BOOL InitAdapters(struct wined3d *wined3d)
} }
} }
/* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
* mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
* but just fake it using D24(X8?) which is fine. D3D also allows that.
* Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
* that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
* driver is allowed to consume more bits EXCEPT for stencil bits.
*
* Mark an adapter with this broken stencil behavior.
*/
adapter->brokenStencil = TRUE;
for (i = 0, cfgs = adapter->cfgs; i < adapter->cfg_count; ++i)
{
/* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
adapter->brokenStencil = FALSE;
break;
}
}
WineD3D_ReleaseFakeGLContext(&fake_gl_ctx); WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode); select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);

View File

@ -1527,7 +1527,6 @@ struct wined3d_adapter
WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */
unsigned int cfg_count; unsigned int cfg_count;
struct wined3d_pixel_format *cfgs; struct wined3d_pixel_format *cfgs;
BOOL brokenStencil; /* Set on cards which only offer mixed depth+stencil */
unsigned int TextureRam; /* Amount of texture memory both video ram + AGP/TurboCache/HyperMemory/.. */ unsigned int TextureRam; /* Amount of texture memory both video ram + AGP/TurboCache/HyperMemory/.. */
unsigned int UsedTextureRam; unsigned int UsedTextureRam;
LUID luid; LUID luid;