Hi,
I have my DIB driver code available on a public git host now: http://repo.or.cz/w/wine/dibdrv.git
I'm going to briefly describe it.
The dib driver (or engine) is a gdi driver. It is loaded into a dc when an application selects a dib, and overrides the existing driver. The magic takes place in SelectBitmap. Safe interaction is provided in gdi32 in four patches. If the winedib.drv.so library is available, then gdi will use the dib driver for drawing into the selected dib. If winedib.drv.so is not available, then gdi will continue using winex11 for example just as before. So these four patches can be safely integrated with the main tree if that is decided to be done.
The rest of the code is the driver itself. It can handle all the standard uncompressed dib formats. It can convert between formats, and it can Get/SetDIBits/Blt. Get/SetPixel is implemented too. No other drawing code is done yet, so only simple GDI apps work. I've tested several apps and I'll list my results.
notepad -- no regressions found winefile -- visual artifacts, but usable bmp loading -- works fine for what has been tested pixel setting -- works fine for every supported format opengl app -- Tribes 1 -- no regressions found d3d app -- Star Wars Battlefront -- no regressions found ddraw app -- Diablo shareware -- no regressions found ddraw app -- Diablo prerelease -- discovered one visual artifact
These are the deficiencies in current code (non-stubs):
No RLE support Missing raster operations in *Blt Get/SetDIBits does not conform exactly yet Bottom-up DIB's not tested for (and probably broken) DIB_PAL_COLORS not tested for No stretching No forwarding calls back to original driver*
*For forwarding back the calls, what I think can be done is use the hbitmap handle originally given, convert it to a DDB, select it, and make the same gdi call again which will then go to the actual device. I do probably need to make sure the dibdrv's physdev persists and doesn't get deleted during this ;) (probably something in Create/Delete DC)
Performance
Originally I was going to state not to expect there really to be any performance improvements. I feel that there are optimizations possible that I have not done, but I left room for. My first concern was correct pixel by pixel operation. So I thought not to expect anything but last night I discovered this, so I might as well share. I have written a program that performs Get/SetPixel to test the various formats. There are 13 total tests, and the program produces 52 MB of output. Just for fun I ran my program without the dib driver and found it took a very long time (I was thinking it hung up at first since it took so long!): timed with winex11.drv real 0m53.903s user 0m19.807s sys 0m5.869s
So I tried it with my driver: timed with winedib.drv real 0m3.924s user 0m3.537s sys 0m0.191s
Indeed, my tests show that there is a 50 second difference with GDI Get/SetPixel. If anyone wants to try my app, I'll send it to them :) Still, I wouldn't expect *your* app to seem much different (or work at all :P)
So will all the interested parties take a look at the driver and I'd sure appreciate feedback on the direction this is going, so we move towards finishing this project beyond the summer of code. :)
Jesse
"Jesse Allen" the3dfxdude@gmail.com writes:
Indeed, my tests show that there is a 50 second difference with GDI Get/SetPixel. If anyone wants to try my app, I'll send it to them :)
Note that GetPixel is the worst possible case under X, since it takes a full server roundtrip for each pixel. So yes, a DIB engine will definitely be faster here, the opposite would be very worrying. Testing just SetPixel would be a more meaningful test however.
Am Donnerstag, 23. August 2007 18:58 schrieb Jesse Allen:
Hi,
I have my DIB driver code available on a public git host now: http://repo.or.cz/w/wine/dibdrv.git
I'm going to briefly describe it.
Is your dib driver an all or nothing replacement of winex11 GDI drawing, or can it be mixed with winex11? How do you deal with BitBlt() or simmilar calls between your driver and winex11?
On 8/23/07, Stefan Dösinger stefandoesinger@gmx.at wrote:
Am Donnerstag, 23. August 2007 18:58 schrieb Jesse Allen:
Hi,
I have my DIB driver code available on a public git host now: http://repo.or.cz/w/wine/dibdrv.git
I'm going to briefly describe it.
Is your dib driver an all or nothing replacement of winex11 GDI drawing, or can it be mixed with winex11?
I think it was decided not to mix the dc_funcs of the drivers. It seems like it would be messy as you have to keep track of which physDev goes where. So I decided to go all or nothing and have replacements for at least every winex11 export to be safe. Forwarding can be done as I described in the first email. I haven't tried yet, since it is still pretty early. Some functions might not be needed, though, like CreateDIBSection or CreateBitmap, but I still stubbed everything so in testing anything that might show up will be easier to identify.
How do you deal with BitBlt() or simmilar calls between your driver and winex11?
I convert the bitmap to the destination device and proceed with the call. See: http://repo.or.cz/w/wine/dibdrv.git?a=commit;h=ad667f577e120ab96125c658679bd...
Jesse
Am Donnerstag, 23. August 2007 20:16 schrieb Jesse Allen:
On 8/23/07, Stefan Dösinger stefandoesinger@gmx.at wrote:
Am Donnerstag, 23. August 2007 18:58 schrieb Jesse Allen:
Hi,
I have my DIB driver code available on a public git host now: http://repo.or.cz/w/wine/dibdrv.git
I'm going to briefly describe it.
Is your dib driver an all or nothing replacement of winex11 GDI drawing, or can it be mixed with winex11?
I think it was decided not to mix the dc_funcs of the drivers. It seems like it would be messy as you have to keep track of which physDev goes where. So I decided to go all or nothing and have replacements for at least every winex11 export to be safe. Forwarding can be done as I described in the first email. I haven't tried yet, since it is still pretty early. Some functions might not be needed, though, like CreateDIBSection or CreateBitmap, but I still stubbed everything so in testing anything that might show up will be easier to identify.
Ya, I've tried forwarding in wined3d, it is a pain. I've decided to drop that idea. What I meant was wether all GDI stuff happens in the new driver now, or if some windows/DIBs/whatevers can use the new code, and some the old.
How do you deal with BitBlt() or simmilar calls between your driver and winex11?
I convert the bitmap to the destination device and proceed with the call. See: http://repo.or.cz/w/wine/dibdrv.git?a=commit;h=ad667f577e120ab96125c658679b d4f8d2a2decc
While you're at it, can you make it more universal so we can add a wined3d driver too, and convince AJ about it?
On 8/23/07, Stefan Dösinger stefandoesinger@gmx.at wrote:
Am Donnerstag, 23. August 2007 20:16 schrieb Jesse Allen:
On 8/23/07, Stefan Dösinger stefandoesinger@gmx.at wrote:
Am Donnerstag, 23. August 2007 18:58 schrieb Jesse Allen:
Hi,
I have my DIB driver code available on a public git host now: http://repo.or.cz/w/wine/dibdrv.git
I'm going to briefly describe it.
Is your dib driver an all or nothing replacement of winex11 GDI drawing, or can it be mixed with winex11?
I think it was decided not to mix the dc_funcs of the drivers. It seems like it would be messy as you have to keep track of which physDev goes where. So I decided to go all or nothing and have replacements for at least every winex11 export to be safe. Forwarding can be done as I described in the first email. I haven't tried yet, since it is still pretty early. Some functions might not be needed, though, like CreateDIBSection or CreateBitmap, but I still stubbed everything so in testing anything that might show up will be easier to identify.
Ya, I've tried forwarding in wined3d, it is a pain. I've decided to drop that idea. What I meant was wether all GDI stuff happens in the new driver now, or if some windows/DIBs/whatevers can use the new code, and some the old.
Not all. It's going to be the same. I'm not planning on changing the driver interface. So I'm planning to make the dib.drv replace winex11 cleanly for DIBs only.
The best way to use the new code is to select in a DIB section into your DC. To use the old code, select in a DDB. I don't know if it's possible to use the driver outside of GDI.
How do you deal with BitBlt() or simmilar calls between your driver and winex11?
I convert the bitmap to the destination device and proceed with the call. See: http://repo.or.cz/w/wine/dibdrv.git?a=commit;h=ad667f577e120ab96125c658679b d4f8d2a2decc
While you're at it, can you make it more universal so we can add a wined3d driver too, and convince AJ about it?
Okay, but the dib driver is special. A dib works on any device, so that's why I can convert between. You're not supposed to blit across different devices. Could you point out your issues with blitting and wined3d?
Jesse
Am Donnerstag, 23. August 2007 20:59 schrieb Jesse Allen:
While you're at it, can you make it more universal so we can add a wined3d driver too, and convince AJ about it?
Okay, but the dib driver is special. A dib works on any device, so that's why I can convert between. You're not supposed to blit across different devices. Could you point out your issues with blitting and wined3d?
Applications are supposed to be able to blit between d3d DCs and "normal" DCs(DIBs mostly). This works currently because wined3d downloads the gl data into a DIB and passes a DC of that DIB to the app. I wanted to improve our performance of GetDC on render targets by writing my own GDI driver, and return a DC whose functions draw directly in opengl, rather than downloading and reuploading.
Nice plan, with one exception: Now I have made d3d surfaces a different device, which they are not supposed to be. Cross-Device blits aren't supposed to work, d3d<->dib blits are. Or are Device Independent Bitmaps a different matter here? I do not think so, as I understand them they belong to the general windowing device class.
Alexandre says that my opengl driver should go into winex11, and he's right with that. On Windows <= XP, d3d is part of gdi, thus the d3d implementation is part of the gdi driver. I am not sure about Vista, but I think they removed it from gdi there to simplify the drivers. Now I do not like the idea of moving wined3d into winex11 or gdi32 altogether, so I'd have to split out the opengl gdi parts.
Now the trouble is, that doesn't work. WineD3D manages the opengl contexts, and the gdi calls would need a context, and specific states set up. This could be fixed by writing a wine-private gl extension to get a hdc on the back buffer, which offers the driver implementation a callback to request a context from the user of the extension(wined3d). Also not a really nice solution.
Another way suggested by Chris was to create GLXPixmaps, copy the back buffer into it, and then have gdi draw on it, then copy them back. The X server can optimize this, and keep the copying and drawing GPU-Side. However, that way we depend on the mercy of X11 and the driver to be able to do the xlib calls on the gpu. I doubt that they do it, but I'll play with this approach a bit more.
The only gdi function I am really interested in is ExtTextOut, and perhaps GetDIBBits. Some games use it to draw text on the back buffer, and they're terribly slow(down to 0.5 fps). I have started a proove of concept implementation[1] which suffered from the Cross-Device BitBlt problem(theoretically, and pop3d used it, but apparently without doing anything with the results).
I do not see any essential difference between your DIB driver and a wined3d driver from the BitBlt point of view.
http://www.winehq.org/pipermail/wine-devel/2007-May/057170.html
On 8/23/07, Stefan Dösinger stefandoesinger@gmx.at wrote:
Am Donnerstag, 23. August 2007 20:59 schrieb Jesse Allen:
While you're at it, can you make it more universal so we can add a wined3d driver too, and convince AJ about it?
Okay, but the dib driver is special. A dib works on any device, so that's why I can convert between. You're not supposed to blit across different devices. Could you point out your issues with blitting and wined3d?
Applications are supposed to be able to blit between d3d DCs and "normal" DCs(DIBs mostly). This works currently because wined3d downloads the gl data into a DIB and passes a DC of that DIB to the app. I wanted to improve our performance of GetDC on render targets by writing my own GDI driver, and return a DC whose functions draw directly in opengl, rather than downloading and reuploading.
...
I do not see any essential difference between your DIB driver and a wined3d driver from the BitBlt point of view.
There is one essential difference. The DIB driver and graphics driver reside in the same DC. I do not have to create another DC to get it to work. And because it is in the same DC, GDI has to be the one that manages the DIB driver internally. To get wined3d to do the same thing here with Blt calls, we would have to move wined3d to be internal to GDI which is something we don't want to do.