http://bugs.winehq.org/show_bug.cgi?id=58662
Bug ID: 58662 Summary: 16-bit bitmap rendering Product: Wine Version: 10.14 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: opengl Assignee: wine-bugs@winehq.org Reporter: zowie+wine@vandillen.io Distribution: ---
Created attachment 79243 --> http://bugs.winehq.org/attachment.cgi?id=79243 Glitchy 16-bit render of Civilization 3. Without OpenGL Civ 3 does not have visible glitches.
I've added a new test earlier today for 16-bit bitmap rendering with wGL [1]. In conclusion, it's pretty broken. The solution to this problem isn't trivial, so I'm opening this issue for discussion.
On Windows, when wglChoosePixelFormat is called with the flag `PFD_DRAW_TO_BITMAP` and `cColorBits = 16`, you'll be given a pixel format with r5g5b5a1 (except that the alpha bit is somewhat quirky). This gives you a software rendered OpenGL context for OpenGL 1.1 [2].
On Wine, asking for a 16-bit pixel format gets you nothing, because all 16-bit pixel formats with the DRAW_TO_BITMAP are required to have an alpha bit in Wine and none of the pixel formats on my Nvidia driver actually have an alpha bit (there's only r5g6b5 and r16). The alpha bit requirement was introduced recently in MR !8392 [3]. It's worth noting that not getting a pixel format — although it's wrong — actually works pretty well for Civilization 3 (see “relevant software” section).
Removing the check for an alpha bit, Wine will be able to find a 16 bit pixel format again, but you'll get unusably bad renders (screenshots in the attachments).
Some observations on the screenshots: - You can see alternating vertical black/blue and orange/white/yellow lines every horizontal pixel. - Blue pixels appear in the black lines, but they're rare. I only see blue pixels in the text in the SimGolf screenshot. - The render buffer doesn't seem to be getting cleared (pretty apparent in Civilization 3: the old squares were sticking around) - Zooming in, you can see that there aren't only vertical lines, but also horizontal lines (see zoomed-in screenshot).
My theory is that there's two problems: - Wine is probably putting 32-bit-per-pixel renders into the 16-bit-per-pixel bitmaps. This explains the vertical & horizontal lines. I'm guessing there's also some memory corruption as a consequence: It's presumably overwriting twice as much bitmap memory as it should. - The right pixel format just doesn't exist. The format r5g5b5a1 is not something that is actually implemented on hardware (at least not anymore), it's just a quirky Windows software renderer thing.
The second point is a bit troublesome because I don't see any easy workarounds. The most obvious solution is to make an OpenGL 1.1 software renderer of our own. Alternatively, it might be possible to simulate the behaviour by using a 32-bits-per-pixel OpenGL context. Whenever glFinish is called, we could download the render to a "secret" Wine-internal bitmap that's also 32 bpp and then overwrite the 16 bpp bitmap based on the pixels of the 32 bpp bitmap. I'm not sure how reliable that is.
Looking at the OpenGL 1.1 reference [4], I think making an OpenGL 1.1 software renderer could be a fun project, but the other solution definitely seems like less effort. I've only been involved in Wine for seven days though, so I'll defer the decision to senior maintainers.
[1] https://gitlab.winehq.org/wine/wine/-/merge_requests/8888 [2] https://www.khronos.org/opengl/wiki/Platform_specifics:_Windows#PFD_DRAW_TO_... [3] https://gitlab.winehq.org/wine/wine/-/merge_requests/8392 [4] https://www.talisman.org/opengl-1.1/Reference.html
---
Relevant software (screenshots in attachments) - Sid Meier's SimGolf (demo: https://archive.org/details/Simgolfdemo) In SimGolf, a 16-bit DRAW_TO_BITMAP OpenGL context seems to be used for drawing the terrain. Currently, the terrain renders as black. - Sid Meier's Civilization 3 In Civilization 3, it seems that 16-bit bitmap rendering is used to draw an outline for the movement range of a selected unit (that's just a guess. It draws a square when a unit is selected but I haven't seen it without glitches). It's notable that Civilization 3 currently works fine. Because wglChoosePixelFormat doesn't find a 16-bit pixel format, the `null_gl` implementation is being used right now. That works out pretty well because the movement range outline isn't something you miss when you don't know it's supposed to be there.
---
Relevant bugs: Sid Meier's SimGolf does not render properly | https://bugs.winehq.org/show_bug.cgi?id=50876 Civilization III Complete shows black terrain (Wine compiled with OSMesa support) | https://bugs.winehq.org/show_bug.cgi?id=41930
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #1 from Zowie zowie+wine@vandillen.io --- Created attachment 79244 --> http://bugs.winehq.org/attachment.cgi?id=79244 SimGolf demo in 16-bit.
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #2 from Zowie zowie+wine@vandillen.io --- Created attachment 79245 --> http://bugs.winehq.org/attachment.cgi?id=79245 Without OpenGL (current Wine master), SimGolf demo has black ground
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #3 from Zowie zowie+wine@vandillen.io --- Created attachment 79246 --> http://bugs.winehq.org/attachment.cgi?id=79246 Zooming in on Civ 3 screenshot, you can see vertical and horizontal lines
http://bugs.winehq.org/show_bug.cgi?id=58662
Rémi Bernon rbernon@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |rbernon@codeweavers.com
--- Comment #4 from Rémi Bernon rbernon@codeweavers.com --- Yeah I think faking the pixel format and fixing up when uploading/downloading the pixels seems the easiest approach here. You can have a look at `flush_memory_dc` in dlls/win32u/opengl.c which is where this is being done with memory DCs.
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #5 from Zowie zowie+wine@vandillen.io --- Alright, I'll get working on that solution.
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #6 from Zowie zowie+wine@vandillen.io --- I've pretty much fixed it, although I still have to fix a BadMatch issue when running the tests with LLVMPipe, as well as tidying it all up for a merge. Do you know of any programs that use 32-bit or 24-bit DRAW_TO_BITMAP rendering? I suspect that a couple issues of issues that I dealt with for 16-bit rendering might apply to those as well.
It's worth mentioning that Civ 3 is very slow to render when any OpenGL elements are on screen. Moving the camera takes about half a second, maybe, rather than being near instant. I suspect it calls glFinish or glFlush a lot, and that leads to a lot of glReadPixels. Fortunately old games expected these things to be slow, and it's not that jarring. SimGolf performs pretty well.
http://bugs.winehq.org/show_bug.cgi?id=58662
Stian Low wineryyyyy@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |wineryyyyy@gmail.com
--- Comment #7 from Stian Low wineryyyyy@gmail.com --- (In reply to Zowie from comment #3)
Created attachment 79246 [details] Zooming in on Civ 3 screenshot, you can see vertical and horizontal lines
Moyo Go Studio regression exhibits vertical lines for stones and may be related and improve by your fixes: https://bugs.winehq.org/show_bug.cgi?id=58620
(In reply to Zowie from comment #6)
Do you know of any programs that use 32-bit or 24-bit DRAW_TO_BITMAP rendering? I suspect that a couple issues of issues that I dealt with for 16-bit rendering might apply to those as well.
Maybe Moyo Go Studio uses bitmap rendering your interested in testing.
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #8 from Zowie zowie+wine@vandillen.io --- I suspect it's something different for Moyo Go Studio, but it could be. 24-bit and 32-bit OpenGL bitmap rendering should already render pretty OK, so I wouldn't expect the vertical lines for those. Nevertheless, I'll take a quick look at it once I've got this fix merged.
http://bugs.winehq.org/show_bug.cgi?id=58662
--- Comment #9 from Zowie zowie+wine@vandillen.io --- (In reply to Stian Low from comment #7) Your guess was right after all — Moyo Go uses a 24-bit PFD_DRAW_TO_BITMAP pbuffer to draw each of the stones. As it turns out 24-bit bitmaps are also broken in much the same ways as 16-bit ones, but the fix is pretty simple. I'll make a merge request for the fix later today.