Hi all,
I've implemented SetClipList and GetClipList in the DirectDraw Clipper, and I'm wondering how I should go about implementing clipping in DirectDraw's Blt() (if it isn't already done somewhere).
M$'s documentation isn't too great, so I figured I should ask around. There's a game one of my relatives wants to run under Linux (it's a children's program), and the major problem is that it dosen't seem to handle clipping properly when blitting. (e.g. every time you move the mouse, it calls SetClipList).
FYI, the binkw32.dll that came with the program was originally causing it to hang, but I patched the DLL and it works fine. If anyone else has had such problems, I could provide a patch.
Also, I'm going to take a look at some of the DirectSound stuff too. The sound isn't very good quality for some reason, but under the WineX 3.3 CVS, sound works perfectly.
Tim
I've implemented SetClipList and GetClipList in the DirectDraw Clipper, and I'm wondering how I should go about implementing clipping in DirectDraw's Blt() (if it isn't already done somewhere).
Usually, games use the Clipper to do 'non-full screen' DirectX applications. There is no way to do a work-around to have it running in full-screen :-) ?
Anyway, all this clipping is not really implemented properly as most of the effort was spent on full screen apps. As far as I can see in the code, the only case supported with clipping is the case where only one rectangle is given in the clip list via the SetHWnd method (see, for example, User_copy_to_screen in dlls/ddraw/dsurface/user.c) which is the 'standard' case for windowed DirectX applications (like Media player) : a menu bar + a DirectX display zone.
After, if the list is only one rectangle, it should be easy to re-use the existing code. Otherwise (ie multiple rectangles), you should check if you can support with the 'BitBlt' API something like the 'XSetClipRectangles' X11 API (which can't be called directly from DirectX anymore) which would prevent us rewriting in the DirectX code some generic 'multi-rectangle' clipping code.
Lionel
On Sat, 3 Apr 2004 10:26:12 +0200 Lionel Ulmer lionel.ulmer@free.fr wrote:
Usually, games use the Clipper to do 'non-full screen' DirectX applications. There is no way to do a work-around to have it running in full-screen :-) ?
While it doesn't make sense it does use the Clipper even in fullscreen mode. :P
A little hacking, using FIXME() to reveal some info (I didn't want to enable TRACE() because it makes the app way too slow :P):
fixme:ddraw:Main_DirectDrawClipper_SetClipList (0x47c9cfe0)->SetClipList(0x49d8cbe0,0) fixme:ddraw:Main_DirectDrawClipper_SetClipList --------- RGNDATA ---------- fixme:ddraw:Main_DirectDrawClipper_SetClipList dwSize: 32 fixme:ddraw:Main_DirectDrawClipper_SetClipList nCount: 3 fixme:ddraw:Main_DirectDrawClipper_SetClipList rcBound: 313,234,365,265 fixme:ddraw:Main_DirectDrawClipper_SetClipList ---------------------------- fixme:ddraw:DIB_DirectDrawSurface_Blt (0x47c9bba8)->(0x406dfd34,0x46c4c640,0x406dfd24,00020000,0x406dfc94) fixme:ddraw:DIB_DirectDrawSurface_Blt destrect :313x234-365x265 fixme:ddraw:DIB_DirectDrawSurface_Blt srcrect :313x234-365x265 fixme:ddraw:DIB_DirectDrawSurface_Blt flags: DDBLT_ROP
Anyway, all this clipping is not really implemented properly as most of the effort was spent on full screen apps.
I might be up for fixing that, at least partially :P
As far as I can see in the code, the only case supported with clipping is the case where only one rectangle is given in the clip list via the SetHWnd method (see, for example, User_copy_to_screen in dlls/ddraw/dsurface/user.c) which is the 'standard' case for windowed DirectX applications (like Media player) : a menu bar + a DirectX display zone.
I'll have a look at that. I did implement SetClipList/GetClipList even though I did it a bit hackishly IMO, it dosen't give any problems :P
Otherwise (ie multiple rectangles), you should check if you can support with the 'BitBlt' API something like the 'XSetClipRectangles' X11 API (which can't be called directly from DirectX anymore) which would prevent us rewriting in the DirectX code some generic 'multi-rectangle' clipping code.
I'm guessing that the current DX implementation uses a user32-based rendering via BitBlit? I know that DX allows for HAL and User32-based drawing.
I'll have a look at the XSetClipRectangles() man page and hope and pray that I can find a way to implement this :P Any further help you could give me would be appreciated.
Thanks,
Tim
On Sat, 3 Apr 2004 04:00:23 -0500 Tim Hentenaar tth@one.net wrote:
As far as I can see in the code, the only case supported with clipping is the case where only one rectangle is given in the clip list via the SetHWnd method (see, for example, User_copy_to_screen in dlls/ddraw/dsurface/user.c) which is the 'standard' case for windowed DirectX applications (like Media player) : a menu bar + a DirectX display zone.
I had a look, and implemented a clip list with one rect to use the same code as with an hWnd since they are virtually the same. This app is wierd in the fact that it dosen't use the hWnd for clipping with one rect, but rather a clip list with one rect. That fixed the drawing somewhat.
Otherwise (ie multiple rectangles), you should check if you can support with the 'BitBlt' API something like the 'XSetClipRectangles' X11 API (which can't be called directly from DirectX anymore) which would prevent us rewriting in the DirectX code some generic 'multi-rectangle' clipping code.
I read through some of the M$ Docs, and it claims that DirectDrawSurface::Blt shouldn't be drawing to any area outside the destination surface's clip list if one exists. I accounted for this, and I'll say that the drawing looks a hell of a lot better, though the app has some now-obvious flaws that aren't apparent under native Winblows (at least when I tested it via VMWare), and in some places the drawing is quite slow. For instance, I noticed that the app sets the clip list, then tries to blit to a destination rect that isn't present in the clip list. I'm guessing that it's meaning to clip the source rect, but why you would clip the source surface is foreign to me. :P
I'll have to dig a little deeper yet to figure this out. The main thing that irks me, is that even with clipping implemented, wherever it has to draw any sort of constant animation it's horribly slow (most of the time). Though when it plays a movie it plays perfectly. I'm guessing this would be a flaw in the game engine.
I wrote an email to the company that made the game, asking for info, and haven't even gotten a responce :/
Tim
On Sat, Apr 03, 2004 at 08:34:38PM -0500, Tim Hentenaar wrote:
I had a look, and implemented a clip list with one rect to use the same code as with an hWnd since they are virtually the same. This app is wierd in the fact that it dosen't use the hWnd for clipping with one rect, but rather a clip list with one rect. That fixed the drawing somewhat.
Well, it's not THAT strange... Ie if you want to use the features of the clipper in, for example, a full screen applications, you do not need to create a HWND which is the size of the rectangle, you can just add your own clip list. And, if the hardware supports clipping with Blits, you gain time as you do not have to do a lot of stuff in the game engine (all the rectangle intersection code).
In OpenGL-land, this is called 'glScissor' :-)
So, if your game uses only one rectangle, it should be pretty easy to map to the current code. Of course, if it uses more than one, some adaptations would be needed :-/
For instance, I noticed that the app sets the clip list, then tries to blit to a destination rect that isn't present in the clip list. I'm guessing that it's meaning to clip the source rect, but why you would clip the source surface is foreign to me. :P
What do you mean by 'a destination rect that isn't present in the clip list' ?
I'll have to dig a little deeper yet to figure this out. The main thing that irks me, is that even with clipping implemented, wherever it has to draw any sort of constant animation it's horribly slow (most of the time). Though when it plays a movie it plays perfectly. I'm guessing this would be a flaw in the game engine.
Oh well, it can be LOTS of stuff... In Windows, they have direct frame buffer access so some games (like MI3) did a lot of updates of the screen (which leads to a lots of traffic in Wine between game memory, X11 and the frame buffer). It works perfectly well in Windows and will be slow as hell in Wine.
Lionel
On Sun, 4 Apr 2004 10:26:34 +0200 Lionel Ulmer lionel.ulmer@free.fr wrote:
Of course, if it uses more than one, some adaptations would be needed :-/
And that it does :/ It seems not to update the screen properly, but then again, it could be something not completely implemented in Wine, or the game engine.
What do you mean by 'a destination rect that isn't present in the clip list' ?
According to M$ DX7 Documentation, DirectDrawSurface::Blt() should only bit to areas that are in the clip list. And apparently 98% of the time that it's trying to blit to a rect that it's not putting in the clip list, it's almost identical to the RGNDATA.rcBound value, so i'm guessing it's for some type of back-buffer used by the engine :P
Oh well, it can be LOTS of stuff... In Windows, they have direct frame buffer access so some games (like MI3) did a lot of updates of the screen (which leads to a lots of traffic in Wine between game memory, X11 and the frame buffer). It works perfectly well in Windows and will be slow as hell in Wine.
Yeah, that is unless the current DD code was rewritten to use GL and also assuming that the person running it had Direct Rendering, but then again, that would take a lot of time to do, and could possibly be horridly slow if the person happened not to have direct rendering :P
I'm also looking at some of the wave driver stuff. WineX's wave driver (at least the OSS driver) does the sound for the game perfectly whereas Wine's wave output sounds rather odd, crackling, and it seems not to flush the buffer properly. :P
Tim
And that it does :/ It seems not to update the screen properly, but then again, it could be something not completely implemented in Wine, or the game engine.
Well, if it asks for multiple clipping rectangles, and from what I found out in the MSDN, they should not overlap.
So you should just have to loop over all the rectangles and do the 'copy_on_screen' as many times as there are rectangles.
Of course, if they overlap, this method will still work except that we would 're-Blit' some parts multiple times (we would just need to do the optimisations later on).
See these pages :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/regions... http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/regions...
According to M$ DX7 Documentation, DirectDrawSurface::Blt() should only bit to areas that are in the clip list. And apparently 98% of the time that it's trying to blit to a rect that it's not putting in the clip list, it's almost identical to the RGNDATA.rcBound value, so i'm guessing it's for some type of back-buffer used by the engine :P
You mean that it's trying to blit to a zone that is not at all in the clip list (ie all of the intersections of the destination rectangles with the rectangles in the clip list are empty) ? It may well be that it's not a bug (why use clip lists if you still need to check in the engine code if you are completely in or not from the lists).
Yeah, that is unless the current DD code was rewritten to use GL and also assuming that the person running it had Direct Rendering, but then again, that would take a lot of time to do, and could possibly be horridly slow if the person happened not to have direct rendering :P
Well, it's in my plans to do the GL 'port'... It could even be done pretty easily (as almost all of the code already exists in the D3D part of the code). It would be mightily hacky, but well, it may even work :-)
What's blocking me is that my 'target' applications is COMI and it uses 8 bit graphics (so I need a GFX card supported paletted textures to really see if I can get a nice speed-up).
I'm also looking at some of the wave driver stuff. WineX's wave driver (at least the OSS driver) does the sound for the game perfectly whereas Wine's wave output sounds rather odd, crackling, and it seems not to flush the buffer properly. :P
For that, Robert and Eric are the experts...
Lionel
On Sun, 4 Apr 2004 10:58:44 +0200 Lionel Ulmer lionel.ulmer@free.fr wrote:
So you should just have to loop over all the rectangles and do the 'copy_on_screen' as many times as there are rectangles.
Of course, if they overlap, this method will still work except that we would 're-Blit' some parts multiple times (we would just need to do the optimisations later on).
Hmm... should this be implemented in DirectDrawSurface::Blt()?
Well, it's in my plans to do the GL 'port'... It could even be done pretty easily (as almost all of the code already exists in the D3D part of the code). It would be mightily hacky, but well, it may even work :-)
I'd say it'd be a bit faster than the current implementation, at least in most cases :P
Sorry it took so long for me to reply, I've had a stroke of bad luck recently and had lost my will to code for a short time, and my will is back :) If there's anything I hate, it's losing my will to code, there isn't much else that's worse :P
Tim
On Sun, 4 Apr 2004, Tim Hentenaar wrote: [...]
I'm also looking at some of the wave driver stuff. WineX's wave driver (at least the OSS driver) does the sound for the game perfectly whereas Wine's wave output sounds rather odd, crackling, and it seems not to flush the buffer properly. :P
Do you have an i810 sound card by any chance?
I'm asking this because there are known problems with sound on i810 soundcards, especially if you are using the Alsa drivers.
It seems to be caused by a kernel bug which is triggered by the full-duplex mode:
http://crossover.codeweavers.com/pipermail/discuss/2003-December/005653.html
Do you use the Linux Alsa sound drivers in OSS emulation mode, or do you use the kernel OSS sound driver?
On Sun, 4 Apr 2004 16:17:29 +0200 (CEST) Francois Gouget fgouget@free.fr wrote:
Do you have an i810 sound card by any chance?
00:1f.5 Multimedia audio controller: Intel Corp. 82801BA/BAM AC'97 Audio (rev 05)
I'm asking this because there are known problems with sound on i810 soundcards, especially if you are using the Alsa drivers.
I'm using the 2.6.0 kernel with the alsa kernel modules, and OSS emulation.
It seems to be caused by a kernel bug which is triggered by the full-duplex mode:
http://crossover.codeweavers.com/pipermail/discuss/2003-December/005653.html
Hmm.. I don't believe that my card is an i810, it could be, but I have the alsa drivers statically linked into my kernel and I forgot exactly which one it is.
Tim
On Sun, 4 Apr 2004, Tim Hentenaar wrote: [...]
00:1f.5 Multimedia audio controller: Intel Corp. 82801BA/BAM AC'97 Audio (rev 05)
[...]
Hmm.. I don't believe that my card is an i810, it could be, but I have the alsa drivers statically linked into my kernel and I forgot exactly which one it is.
It looks like an i810 to me (but I have never actually seen one so...)
Do you know if it is integrated on the motherboard? And then is it an Intel chipset?
Also, cat /proc/asound/cards will tell you what type of sound card you have.
On Mon, 5 Apr 2004 02:20:51 +0200 (CEST) Francois Gouget fgouget@free.fr wrote:
It looks like an i810 to me (but I have never actually seen one so...)
Do you know if it is integrated on the motherboard? And then is it an Intel chipset?
Also, cat /proc/asound/cards will tell you what type of sound card you have.
0 [I82801BAICH2 ]: ICH - Intel 82801BA-ICH2 Intel 82801BA-ICH2 at 0x1200, irq 10
apparently it's an ICH2 and not an i810, and yes it is integrated on the motherboard. (My computer is a laptop :P)
The odd thing about it is that the sound works fine in WineX (after a little hacking to get it to even run the app :/).
Tim