[RESEND] [ddraw] Mipmap creation with DDSCAPS_COMPLEX, DDSCAPS_MIPMAP, and no mipmap count
Antoine Chavasse
a.chavasse at gmail.com
Sun May 29 14:15:06 CDT 2005
Resend of http://www.winehq.org/hypermail/wine-patches/2005/05/0655.html
With this suggestion from Lionel Ulmer:
> The only (minor) gripe I would have with this patch is the use of the 'log()
> / log()' to compute the mipmap count (I usually dislike floating point match
> - it's maybe my background in embedded programming where FPU are inexistant
> :-) )... I would have found it simpler to just have a 'while (min > 0) { min
> >>= 1; count += 1 }'.
ChangeLog:
- Implemented the implicit creation of mipmaps for surfaces that have
DDSCAPS_COMPLEX, DDSCAPS_MIPMAP and for which the mipmap count is not
specified.
- Implemented test cases for mipmap textures creation.
Index: dlls/ddraw/ddraw/main.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/ddraw/main.c,v
retrieving revision 1.60
diff -u -p -r1.60 main.c
--- dlls/ddraw/ddraw/main.c 27 May 2005 20:17:36 -0000 1.60
+++ dlls/ddraw/ddraw/main.c 29 May 2005 18:54:43 -0000
@@ -430,12 +430,31 @@ create_texture(IDirectDrawImpl* This, co
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;
Index: dlls/ddraw/tests/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/tests/Makefile.in,v
retrieving revision 1.3
diff -u -p -r1.3 Makefile.in
--- dlls/ddraw/tests/Makefile.in 16 Feb 2004 22:18:59 -0000 1.3
+++ dlls/ddraw/tests/Makefile.in 29 May 2005 18:54:43 -0000
@@ -6,7 +6,8 @@ TESTDLL = ddraw.dll
IMPORTS = ddraw user32 gdi32 kernel32
CTESTS = \
- ddrawmodes.c
+ ddrawmodes.c \
+ dsurface.c
@MAKE_TEST_RULES@
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/ddraw/tests/dsurface.c 2005-05-29 18:48:48.554096960 +0200
@@ -0,0 +1,162 @@
+/*
+ * Unit tests for (a few) ddraw surface functions
+ *
+ * Copyright (C) 2005 Antoine Chavasse (a.chavasse at 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 <assert.h>
+#include "wine/test.h"
+#include "ddraw.h"
+
+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;
+ 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(ddsd.dwMipMapCount == 3, "Incorrect mipmap count: %ld.\n",
+ 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(ddsd.dwMipMapCount == 1, "Incorrect mipmap count: %ld.\n",
+ 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(ddsd.dwMipMapCount == 6, "Incorrect mipmap count: %ld.\n",
+ 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(ddsd.dwMipMapCount == 6, "Incorrect mipmap count: %ld.\n",
+ ddsd.dwMipMapCount);
+
+ /* Destroy the surface. */
+ IDirectDrawSurface_Release(lpDDSMipMapTest);
+}
+
+
+START_TEST(dsurface)
+{
+ CreateDirectDraw();
+ MipMapCreationTest();
+ ReleaseDirectDraw();
+}
More information about the wine-patches
mailing list