Complex Surfaces patch

Marius Grigoriu <[email protected]> Mon, 09 Aug 2004 21:13:14 -0400
Newsgroups gmane.comp.emulators.winex.devel
Message-ID <[email protected]>
With this patch, Anarchy Online seems to work 100%, thout it is a bit 
slow when there is more geometry, but i'll blame ATI for now. AO creates 
complex surfaces for its mipmaps, but does not set dwMipMapCount. Before 
the patch, the additional surfaces are not created causing the game to 
crash when it loads an outdoor zone because it expects a certain number 
of surfaces in the chain. In newer documentation, it states that 
DDSCAPS_COMPLEX is used to create a chain of surfaces during the 
CreateSurface call. According to DX3 documentation, "It is permissible 
to omit the number of mipmaps levels, in which case CreateSurface() will 
create a chain of surfaces each a power of two smaller than the previous 
one down to the smallest possible size." Using a test app shows that it 
is still true in DX7. A 128x128 sized surface creates a chain of 8 
surfaces (7 mipmaps + original surface). The attached patch doesn't 
quite do this (because of a problem) but comes close.

According to the test app the length of a chain is based on the largest 
dimension of the first surface. 128x64 -> 8 total surfaces, 64x64 -> 7 
total surfaces. Initially, I set the mipmap count dynamically to behave 
like this. Thought it worked properly in the test app--which just 
creates the surface and counts attached surfaces then quits--the game 
seems to deadlock at a later point if there are more than 6 attached 
surfaces, so I limit the total chain length to 7. You can see this in 
the patch.

I hope that this patch is approved. It's exciting to see that I've been 
able to bring this game such a far way, to the point where it can 
actually be played.

Marius Grigoriu
complex_mipmap.patch (text/x-patch, 1.6 KB)
? complex_mipmap.patch
Index: main.c
===================================================================
RCS file: /cvsroot/winex/dlls/ddraw/ddraw/main.c,v
retrieving revision 1.77
diff -r1.77 main.c
325a326,347
> 	DWORD max;
> 	DDSURFACEDESC2 mipmap_surface_desc;
> 
> 	mipmap_surface_desc = *pDDSD;
> 
> 	/* A somewhat undocumented feature, if DDSCAPS_COMPLEX is set,
> 	 * "It is permissible to omit the number of mipmaps levels, in which case
> 	 * CreateSurface() will create a chain of surfaces each a power of two
> 	 * smaller than the previous one down to the smallest possible size."
> 	 */
> 	if(!(mipmap_surface_desc.dwFlags & DDSD_MIPMAPCOUNT) &&
> 		(mipmap_surface_desc.ddsCaps.dwCaps & DDSCAPS_COMPLEX) &&
> 		(mipmap_surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)){
> 		DDRAW_dump_surface_desc(pDDSD);
> 		max = (mipmap_surface_desc.dwWidth > mipmap_surface_desc.dwHeight) ? 
> 			mipmap_surface_desc.dwWidth : mipmap_surface_desc.dwHeight;
> 		/* FIXME: Adding more than 6 surfaces seems to break things, regardless
> 		 * of original size so we deviate a little from what windows does
> 		 */
> 		mipmap_surface_desc.u2.dwMipMapCount = 7;//log(max)/log(2) + 2;
> 		mipmap_surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
> 	}
327c349
<     hr = This->create_texture(This, pDDSD, ppSurf, pUnkOuter, mipmap_level);
---
>     hr = This->create_texture(This, &mipmap_surface_desc, ppSurf, pUnkOuter, mipmap_level);
331c353
<     if (more_mipmaps(pDDSD))
---
>     if (more_mipmaps(&mipmap_surface_desc))
335d356
< 	DDSURFACEDESC2 mipmap_surface_desc;
339d359
< 	mipmap_surface_desc = *pDDSD;