VOGONS


First post, by 0x1F9F1

User metadata
Rank Newbie
Rank
Newbie

The surface returned from IDirectDrawSurface4::Lock sometimes has an lPitch less than dwWidth * ddpfPixelFormat.dwRGBBitCount (half, to be precise). For example:

'T_WALK_ALLEY' is opaque texture
Surface 64 x 64 (128 pitch, 32 bpp), (ff0000,ff00,ff,0), 7 mipmaps
Invalid Pitch: 128 < 256
Surface 32 x 32 (128 pitch, 32 bpp), (ff0000,ff00,ff,0), 0 mipmaps
Surface 16 x 16 (64 pitch, 32 bpp), (ff0000,ff00,ff,0), 0 mipmaps
Surface 8 x 8 (32 pitch, 32 bpp), (ff0000,ff00,ff,0), 0 mipmaps
Surface 4 x 4 (16 pitch, 32 bpp), (ff0000,ff00,ff,0), 0 mipmaps
Surface 2 x 2 (8 pitch, 32 bpp), (ff0000,ff00,ff,0), 0 mipmaps
Surface 1 x 1 (4 pitch, 32 bpp), (ff0000,ff00,ff,0), 0 mipmaps

'L_BOTTOM' is alpha texture
Surface 64 x 64 (128 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 7 mipmaps
Invalid Pitch: 128 < 256
Surface 32 x 32 (128 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 0 mipmaps
Surface 16 x 16 (64 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 0 mipmaps
Surface 8 x 8 (32 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 0 mipmaps
Surface 4 x 4 (16 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 0 mipmaps
Surface 2 x 2 (8 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 0 mipmaps
Surface 1 x 1 (4 pitch, 32 bpp), (ff0000,ff00,ff,ff000000), 0 mipmaps

This issue only seems to occur with the first surface of most mipmapped 32-bit surface. Using 16-bit surfaces, or disabling mipmaps via dwMipMapCount=0, dwFlags&=~DDSD_MIPMAPCOUNT seems to avoid the problem. Tested with 2.63.2, the debug layer also shows no warnings/errors, and this problem doesn't occur with native DDRAW.

Reply 2 of 5, by 0x1F9F1

User metadata
Rank Newbie
Rank
Newbie

The game is Midtown Madness 1 with some patches. I did some testing and you are right about about the invalid pitch being app defined, as the DDSURFACEDESC2 is loaded from a 16-bit image, but then the ddpfPixelFormat of that surface is overwritten with a 32-bit format, before being passed to CreateSurface. Clearing DDSD_PITCH from dwFlags fixes the problem, though i'm still a bit confused why disabling mipmaps also fixed it.

Reply 3 of 5, by Dege

User metadata
Rank Oldbie
Rank
Oldbie

Yes, it's strange. Pitch and ptr cannot be app-defined for multilevel textures because the incoming DDSURFACEDESC struct only describes the properties of the first level and ptr/pitch cannot be automatically derived for the others.
You should have encountered the following error message from the debug layer:

CreateSurface: Surface ptr (DDSD_LPSURFACE) or pitch/linear size (DDSD_PITCH / DDSD_LINEARSIZE) cannot be defined if the texture has multiple mipmap levels because these properties cannot be inherited in subsequent levels.

What are the ddsCaps and dwFlags members that are passed in? Maybe it's a bug or sg in dgVoodoo causing missing the error condition.

Reply 4 of 5, by 0x1F9F1

User metadata
Rank Newbie
Rank
Newbie

Broken
7C0000000F10020040000000400000008000000000000000070000000000000000000000F057BF200000000000000000000000000000000000000000000000000000000000000000200000004100000000000000200000000000FF0000FF0000FF000000000000FF0810400010000000000000000000000000000000

Works (Disabled mipmaps)
7C0000000F10000040000000400000008000000000000000000000000000000000000000F057BC200000000000000000000000000000000000000000000000000000000000000000200000004100000000000000200000000000FF0000FF0000FF000000000000FF0010000010000000000000000000000000000000

Works (Cleared DDSD_PITCH)
7C0000000710020040000000400000008000000000000000070000000000000000000000F057B0200000000000000000000000000000000000000000000000000000000000000000200000004100000000000000200000000000FF0000FF0000FF000000000000FF0810400010000000000000000000000000000000

The debug layer doesn't show any errors
[dgVoodoo] INFO: DirectDraw (032E6F60)::CreateSurface: Texture is created, head DirectDrawSurface (345B7248).
DirectDrawSurface::AddRef (this = 345B7248)
DirectDrawSurface::Lock (this = 345B7248, lpDestRect = 00000000, lpDDSurfaceDesc = 0019E668, dwFlags = 1, hEvent = 0)
DirectDrawSurface::Unlock (this = 345B7248, lpRect = 00000000)

Reply 5 of 5, by Dege

User metadata
Rank Oldbie
Rank
Oldbie

I looked into the code and it came to my mind that I wanted to remove the custom pitch-feature from CreateSurface (it doesn't exist in MS Ddraw as you said).
I think the expected working mode would be accepting the DDSD_PITCH flag but completely ignore the pitch member and let that be calculated from the width and pixel format.
Maybe when DDSD_LPSURFACE and DDSD_PITCH together is specified then it should be accepted unchanged.

'Broken' case is when DDSCAPS_COMPLEX flag is specified. I'll only remove everything (fix it) in the next tested version to not potentially break existing compatibility with DDraw/D3D games (as I did it earlier).