Let me start off with an introduction. I'm a veteran C programmer, but I'm
unfamiliar with programming X11 and unfamiliar with wine, although I've been
looking into both recently to correct a problem I'm having with wine. I
posted about the same problem in August on the same mailing list, about
making function parameters const. This was a simplistic solution, but I
suggested it simply because I didn't feel I had the time to familiarize
myself with all the inner-workings of wine. Now, I believe I do have the
time.
To repeat the situation, I found that in several of the games I like to run,
the same problem is causing wine to be slow: using oprofile, I find that
nearly all of wine's CPU usage lies in x11drv, and 98-99% of the cpu usage
in x11drv is taken up by calls to some of the convert functions in
dib_convert.c. For example, in Civilization 3, some 98% of the CPU usage in
x11drv is taken up by two functions: convert_555_to_565_asis, and
convert_565_to_555_asis. This summer I had a similar problem on my laptop,
where fce ultra was using the function convert_888_to_0888_asis for most of
its cpu.
Essentially, it seems that most of the work wine is doing when running these
programs is just for converting between one pixel format and back, and I
hope to find a good solution to this speed problem, preferably through
caching. I'm writing to this list in hope of other more experienced wine
hackers giving their advice, telling me what is possible, and what the best
solution is, before I go too far on my own with this.
I'm looking at a group of related functions in wine, in dlls/x11drv/dib.c.
It came to my attention that in X11DRV_SetDIBits and
X11DRV_SetDIBitsToDevice, wine always seems to end up calling
X11DRV_DIB_SetImageBits, which calls (in my case, probably because my
desktop is 16-bit color) X11DRV_DIB_SetImageBits_16, which in every case
calls a convert function of one type or another (all of which are CPU hogs).
These are the core functions that seem to be related to the problem.
Here is my early analysis of the problem: X11DRV_DIB_SetImageBits always
creates and destroys an XImage during the life of the function, and calls
X11DRV_DIB_SetImageBits_16 (or another bit depth), which ends up converting
the bitmap to the proper color format / bit depth. It seems to me the best
solution is to use some kind of caching to save the converted bitmap in its
cached form, preferably as an XImage. Inside X_PHYSBITMAP the HBITMAP is
stored, windows' unique handle for that particular bitmap. So, what if we
stored the appropriate converted XImage per-HBITMAP, per-bpp, so that it
doesn't need to be created, converted, and destroyed each time, and we could
delete all cached XImages corresponding to the HBITMAP from the cache when
DeleteObject() is called for that HBITMAP?
I'm doing a lot of guesswork on the inner-workings of wine, X, and the
windows GDI here. Please tell me, am I on the right track for eliminating
these unnecessary conversions? If not, where should I be looking? Again I'm
new to wine, X, and somewhat new to GDI programming - but I would like to
learn. Please, GDI/X11 experts, give me some advice on the best solution to
this problem!