From bc64485b3a1de00926c9e8f2b5da21e534f01a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C4=8Dardas=20Barkauskas?= Date: Sun, 8 May 2011 17:54:54 +0300 Subject: ddraw: Fix filtering of enumerated display modes --- dlls/ddraw/ddraw.c | 26 +++---- dlls/ddraw/tests/ddrawmodes.c | 166 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 21 deletions(-) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 9b87b95..a4e09b0 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -2070,7 +2070,8 @@ static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_de * the DDSD parameter. * * Params: - * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES + * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw + * versions (3 and older?) this is reserved and must be 0. * DDSD: Surface description to filter the modes * Context: Pointer passed back to the callback function * cb: Application-provided callback function @@ -2085,11 +2086,11 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, { IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); unsigned int modenum, fmt; - enum wined3d_format_id pixelformat = WINED3DFMT_UNKNOWN; WINED3DDISPLAYMODE mode; DDSURFACEDESC2 callback_sd; WINED3DDISPLAYMODE *enum_modes = NULL; unsigned enum_mode_count = 0, enum_mode_array_size = 0; + DDPIXELFORMAT pixelformat; static const enum wined3d_format_id checkFormatList[] = { @@ -2109,12 +2110,6 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, return DDERR_INVALIDPARAMS; } - if(DDSD) - { - if ((DDSD->dwFlags & DDSD_PIXELFORMAT) && (DDSD->u4.ddpfPixelFormat.dwFlags & DDPF_RGB) ) - pixelformat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat); - } - if(!(Flags & DDEDM_REFRESHRATES)) { enum_mode_array_size = 16; @@ -2127,21 +2122,21 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, } } + pixelformat.dwSize = sizeof(pixelformat); for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++) { - if(pixelformat != WINED3DFMT_UNKNOWN && checkFormatList[fmt] != pixelformat) - { - continue; - } - modenum = 0; while (wined3d_enum_adapter_modes(This->wineD3D, WINED3DADAPTER_DEFAULT, checkFormatList[fmt], modenum++, &mode) == WINED3D_OK) { + PixelFormat_WineD3DtoDD(&pixelformat, mode.Format); if(DDSD) { if(DDSD->dwFlags & DDSD_WIDTH && mode.Width != DDSD->dwWidth) continue; if(DDSD->dwFlags & DDSD_HEIGHT && mode.Height != DDSD->dwHeight) continue; + if(DDSD->dwFlags & DDSD_REFRESHRATE && mode.RefreshRate != DDSD->u2.dwRefreshRate) continue; + if (DDSD->dwFlags & DDSD_PIXELFORMAT && + pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount) continue; } if(!(Flags & DDEDM_REFRESHRATES)) @@ -2170,17 +2165,16 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, callback_sd.dwSize = sizeof(callback_sd); callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); - callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH; + callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE; if(Flags & DDEDM_REFRESHRATES) { - callback_sd.dwFlags |= DDSD_REFRESHRATE; callback_sd.u2.dwRefreshRate = mode.RefreshRate; } callback_sd.dwWidth = mode.Width; callback_sd.dwHeight = mode.Height; - PixelFormat_WineD3DtoDD(&callback_sd.u4.ddpfPixelFormat, mode.Format); + callback_sd.u4.ddpfPixelFormat=pixelformat; /* Calc pitch and DWORD align like MSDN says */ callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.Width; diff --git a/dlls/ddraw/tests/ddrawmodes.c b/dlls/ddraw/tests/ddrawmodes.c index a103d65..126fbaf 100644 --- a/dlls/ddraw/tests/ddrawmodes.c +++ b/dlls/ddraw/tests/ddrawmodes.c @@ -39,6 +39,9 @@ static int modes_size; static LPDDSURFACEDESC modes; static RECT rect_before_create; static RECT rect_after_delete; +static int modes16bpp_cnt; +static int refresh_rate; +static int refresh_rate_cnt; static HRESULT (WINAPI *pDirectDrawEnumerateA)(LPDDENUMCALLBACKA,LPVOID); static HRESULT (WINAPI *pDirectDrawEnumerateW)(LPDDENUMCALLBACKW,LPVOID); @@ -344,8 +347,8 @@ static void flushdisplaymodes(void) static HRESULT WINAPI enummodescallback(LPDDSURFACEDESC lpddsd, LPVOID lpContext) { - trace("Width = %i, Height = %i, Refresh Rate = %i, Pitch = %i, flags =%02X\n", - lpddsd->dwWidth, lpddsd->dwHeight, + trace("Width = %i, Height = %i, bpp = %i, Refresh Rate = %i, Pitch = %i, flags =%02X\n", + lpddsd->dwWidth, lpddsd->dwHeight, U1(lpddsd->ddpfPixelFormat).dwRGBBitCount, U2(*lpddsd).dwRefreshRate, U1(*lpddsd).lPitch, lpddsd->dwFlags); /* Check that the pitch is valid if applicable */ @@ -365,6 +368,56 @@ static HRESULT WINAPI enummodescallback(LPDDSURFACEDESC lpddsd, LPVOID lpContext */ adddisplaymode(lpddsd); + if(U1(lpddsd->ddpfPixelFormat).dwRGBBitCount == 16) + modes16bpp_cnt++; + + return DDENUMRET_OK; +} + +static HRESULT WINAPI enummodescallback_16bit(LPDDSURFACEDESC lpddsd, LPVOID lpContext) +{ + trace("Width = %i, Height = %i, bpp = %i, Refresh Rate = %i, Pitch = %i, flags =%02X\n", + lpddsd->dwWidth, lpddsd->dwHeight, U1(lpddsd->ddpfPixelFormat).dwRGBBitCount, + U2(*lpddsd).dwRefreshRate, U1(*lpddsd).lPitch, lpddsd->dwFlags); + + ok(lpddsd->dwFlags == (DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE), + "Wrong surface description flags %02X\n", lpddsd->dwFlags); + ok(lpddsd->ddpfPixelFormat.dwFlags == DDPF_RGB, "Wrong pixel format flag %02X\n", + lpddsd->ddpfPixelFormat.dwFlags); + ok(U1(lpddsd->ddpfPixelFormat).dwRGBBitCount == 16, "Expected 16 bpp got %i\n", + U1(lpddsd->ddpfPixelFormat).dwRGBBitCount); + + /* Check that the pitch is valid if applicable */ + if(lpddsd->dwFlags & DDSD_PITCH) + { + ok(U1(*lpddsd).lPitch != 0, "EnumDisplayModes callback with bad pitch\n"); + } + + if(!refresh_rate) + { + if(U2(*lpddsd).dwRefreshRate ) + { + refresh_rate = U2(*lpddsd).dwRefreshRate; + refresh_rate_cnt++; + } + } + else + { + if(refresh_rate == U2(*lpddsd).dwRefreshRate) + refresh_rate_cnt++; + } + + modes16bpp_cnt++; + + return DDENUMRET_OK; +} + +static HRESULT WINAPI enummodescallback_count(LPDDSURFACEDESC lpddsd, LPVOID lpContext) +{ + ok(lpddsd->dwFlags == (DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE), + "Wrong surface description flags %02X\n", lpddsd->dwFlags); + + modes16bpp_cnt++; return DDENUMRET_OK; } @@ -373,15 +426,118 @@ static void enumdisplaymodes(void) { DDSURFACEDESC ddsd; HRESULT rc; + int count, refresh_count; ZeroMemory(&ddsd, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - rc = IDirectDraw_EnumDisplayModes(lpDD, - DDEDM_STANDARDVGAMODES, &ddsd, 0, enummodescallback); - ok(rc==DD_OK || rc==E_INVALIDARG,"EnumDisplayModes returned: %x\n",rc); + /* Flags parameter is reserved in very old ddraw versions (3 and older?) and must be 0 */ + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback); + ok(rc==DD_OK, "EnumDisplayModes returned: %x\n",rc); + + count = modes16bpp_cnt; + + modes16bpp_cnt = 0; + ddsd.dwFlags = DDSD_PIXELFORMAT; + //ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16; + U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x7C00; + U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x03E0; + U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001F; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK, "EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + modes16bpp_cnt = 0; + U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x0000; + U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000; + U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK, "EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + modes16bpp_cnt = 0; + U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xF0F0; + U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0F00; + U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000F; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK, "EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + + modes16bpp_cnt = 0; + ddsd.ddpfPixelFormat.dwFlags = DDPF_YUV; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + modes16bpp_cnt = 0; + ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + modes16bpp_cnt = 0; + ddsd.dwFlags = DDSD_PIXELFORMAT; + ddsd.ddpfPixelFormat.dwFlags = 0; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + modes16bpp_cnt = 0; + ddsd.dwFlags = 0; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_count); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == modes_cnt, "Expected %d modes got %d\n", modes_cnt, modes16bpp_cnt); + + modes16bpp_cnt = 0; + ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_PITCH; + ddsd.lPitch = 123; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == count, "Expected %d modes got %d\n", count, modes16bpp_cnt); + + modes16bpp_cnt = 0; + ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_REFRESHRATE; + ddsd.dwRefreshRate = 1; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == 0, "Expected 0 modes got %d\n", modes16bpp_cnt); + + modes16bpp_cnt = 0; + ddsd.dwFlags = DDSD_PIXELFORMAT; + + rc = IDirectDraw_EnumDisplayModes(lpDD, DDEDM_REFRESHRATES, &ddsd, 0, enummodescallback_16bit); + if(rc == DDERR_INVALIDPARAMS) + { + skip("Ddraw version too old. Skipping.\n"); + return; + } + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + refresh_count = refresh_rate_cnt; + + if(refresh_rate) + { + modes16bpp_cnt = 0; + ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_REFRESHRATE; + ddsd.dwRefreshRate = refresh_rate; + + rc = IDirectDraw_EnumDisplayModes(lpDD, 0, &ddsd, 0, enummodescallback_16bit); + ok(rc==DD_OK,"EnumDisplayModes returned: %x\n",rc); + ok(modes16bpp_cnt == refresh_count, "Expected %d modes got %d\n", refresh_count, modes16bpp_cnt); + } } static void setdisplaymode(int i) -- 1.7.5.1