diff --git a/dlls/ddraw/ddraw/main.c b/dlls/ddraw/ddraw/main.c index 321a2a10caa..d0c4e1b46f0 100644 --- a/dlls/ddraw/ddraw/main.c +++ b/dlls/ddraw/ddraw/main.c @@ -430,12 +430,31 @@ create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2 *pDDSD, ddsd.dwFlags |= DDSD_PITCH; } - /* Check also for the MIPMAP / MIPMAPCOUNT flags. - As checked on Windows, this is the right behaviour. No mipmaps seem to be generated. */ - if (((ddsd.dwFlags & DDSD_MIPMAPCOUNT) == 0) && - ((ddsd.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != 0)) { + if((ddsd.ddsCaps.dwCaps & DDSCAPS_MIPMAP) && + !(ddsd.dwFlags & DDSD_MIPMAPCOUNT)) + { + if(ddsd.ddsCaps.dwCaps & DDSCAPS_COMPLEX) + { + /* Undocumented feature: if DDSCAPS_MIPMAP and DDSCAPS_COMPLEX are + * both set, but mipmap count isn't given, as many mipmap levels + * as necessary are created to get down to a size where either + * the width or the height of the texture is 1. + * + * This is needed by Anarchy Online. */ + DWORD min = ddsd.dwWidth < ddsd.dwHeight ? + ddsd.dwWidth : ddsd.dwHeight; + ddsd.u2.dwMipMapCount = 0; + while( min ) + { + ddsd.u2.dwMipMapCount++; + min >>= 1; + } + } + else + /* Create a single mipmap. */ + ddsd.u2.dwMipMapCount = 1; + ddsd.dwFlags |= DDSD_MIPMAPCOUNT; - ddsd.u2.dwMipMapCount = 1; } ddsd.dwFlags |= DDSD_PIXELFORMAT; diff --git a/dlls/ddraw/tests/.cvsignore b/dlls/ddraw/tests/.cvsignore index 6cda753e15c..407994b413d 100644 --- a/dlls/ddraw/tests/.cvsignore +++ b/dlls/ddraw/tests/.cvsignore @@ -1,3 +1,4 @@ Makefile ddrawmodes.ok +dsurface.ok testlist.c diff --git a/dlls/ddraw/tests/Makefile.in b/dlls/ddraw/tests/Makefile.in index 1f80aa401a7..4603cdf0ded 100644 --- a/dlls/ddraw/tests/Makefile.in +++ b/dlls/ddraw/tests/Makefile.in @@ -6,7 +6,8 @@ TESTDLL = ddraw.dll IMPORTS = ddraw user32 gdi32 kernel32 CTESTS = \ - ddrawmodes.c + ddrawmodes.c \ + dsurface.c @MAKE_TEST_RULES@ diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c new file mode 100644 index 00000000000..86390f8ad58 --- /dev/null +++ b/dlls/ddraw/tests/dsurface.c @@ -0,0 +1,170 @@ +/* + * Unit tests for (a few) ddraw surface functions + * + * Copyright (C) 2005 Antoine Chavasse (a.chavasse@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "wine/test.h" +#include "ddraw.h" + +#ifdef NONAMELESSUNION +# define U(x) (x).u +# define U2(x) (x).u2 +#else +# define U(x) (x) +# define U2(x) (x) +#endif + +static LPDIRECTDRAW lpDD = NULL; + +static void CreateDirectDraw() +{ + HRESULT rc; + + rc = DirectDrawCreate(NULL, &lpDD, NULL); + ok(rc==DD_OK,"DirectDrawCreate returned: %lx\n",rc); + + rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL); + ok(rc==DD_OK,"SetCooperativeLevel returned: %lx\n",rc); +} + + +static void ReleaseDirectDraw() +{ + if( lpDD != NULL ) + { + IDirectDraw_Release(lpDD); + lpDD = NULL; + } +} + +static void MipMapCreationTest() +{ + LPDIRECTDRAWSURFACE lpDDSMipMapTest; + DDSURFACEDESC ddsd; + HRESULT rc; + + /* First mipmap creation test: create a surface with DDSCAPS_COMPLEX, + DDSCAPS_MIPMAP, and DDSD_MIPMAPCOUNT. This create the number of + requested mipmap levels. */ + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + U2(ddsd).dwMipMapCount = 3; + ddsd.dwWidth = 128; + ddsd.dwHeight = 32; + rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL); + ok(rc==DD_OK,"CreateSurface returned: %lx\n",rc); + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd); + ok(rc==DD_OK,"GetSurfaceDesc returned: %lx\n",rc); + ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT, + "GetSurfaceDesc returned no mipmapcount.\n"); + ok(U2(ddsd).dwMipMapCount == 3, "Incorrect mipmap count: %ld.\n", + U2(ddsd).dwMipMapCount); + + /* Destroy the surface. */ + IDirectDrawSurface_Release(lpDDSMipMapTest); + + + /* Second mipmap creation test: create a surface without a mipmap + count, with DDSCAPS_MIPMAP and without DDSCAPS_COMPLEX. + This creates a single mipmap level. */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + ddsd.dwWidth = 128; + ddsd.dwHeight = 32; + rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL); + ok(rc==DD_OK,"CreateSurface returned: %lx\n",rc); + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd); + ok(rc==DD_OK,"GetSurfaceDesc returned: %lx\n",rc); + ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT, + "GetSurfaceDesc returned no mipmapcount.\n"); + ok(U2(ddsd).dwMipMapCount == 1, "Incorrect mipmap count: %ld.\n", + U2(ddsd).dwMipMapCount); + + + /* Third mipmap creation test: create a surface with DDSCAPS_MIPMAP, + DDSCAPS_COMPLEX and without DDSD_MIPMAPCOUNT. + It's an undocumented features where a chain of mipmaps, starting from + he specified size and down to the smallest size, is automatically + created. + Anarchy Online needs this feature to work. */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = 128; + ddsd.dwHeight = 32; + rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL); + ok(rc==DD_OK,"CreateSurface returned: %lx\n",rc); + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd); + ok(rc==DD_OK,"GetSurfaceDesc returned: %lx\n",rc); + ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT, + "GetSurfaceDesc returned no mipmapcount.\n"); + ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %ld.\n", + U2(ddsd).dwMipMapCount); + + + /* Fourth mipmap creation test: same as above with a different texture + size. + The purpose is to verify that the number of generated mipmaps is + dependant on the smallest dimension. */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = 32; + ddsd.dwHeight = 64; + rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL); + ok(rc==DD_OK,"CreateSurface returned: %lx\n",rc); + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(ddsd); + rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd); + ok(rc==DD_OK,"GetSurfaceDesc returned: %lx\n",rc); + ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT, + "GetSurfaceDesc returned no mipmapcount.\n"); + ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %ld.\n", + U2(ddsd).dwMipMapCount); + + /* Destroy the surface. */ + IDirectDrawSurface_Release(lpDDSMipMapTest); +} + + +START_TEST(dsurface) +{ + CreateDirectDraw(); + MipMapCreationTest(); + ReleaseDirectDraw(); +}