https://bugs.winehq.org/show_bug.cgi?id=39421
Bug ID: 39421 Summary: Majesty Gold HD runs very slowly Product: Wine Version: 1.7.52 Hardware: x86 OS: Mac OS X Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: jonas.bugzilla@gmail.com
Created attachment 52535 --> https://bugs.winehq.org/attachment.cgi?id=52535 Clamp the glFlush rate in the Mac driver to 60Hz
The game Majesty Gold HD (http://www.gog.com/game/majesty_gold_hd ) runs very slowly under Wine for me (Late 2013 iMac 21.5", quad 2.9GHz Core i5, GeForce GT 750M with 1GB GDDR5, OS X 10.9.5). There is an in-game slider to speed up the game, but it has no effect.
The game is a DirectDraw 7 game. There are also some reports on Windows regarding this problem, but most people can solve it by telling the game to use DirectDraw for blitting (set BlitMode=1 in the MajXPrefs, or use the -useddblit command line parameter -- see http://forum.paradoxplaza.com/forum/index.php?threads/bug-fixes.601217/#post... )
The game performs its drawing commands in the same thread that runs the game logic (I don't know whether anything else is even supported by by DirectDraw 7). From a trace I can see that game performs many small blits to update only the parts of the screen that have changed. Example from a trace:
trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (0,0)-(24,38), src_surface 0x16c9c8, src_rect (0,0)-(24,38), flags 0x1000000, fx 0x0. [ repeats 8 times ] trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (864,661)-(1009,803), src_surface 0x16c9c8, src_rect (864,661)-(1009,803), flags 0x1000000, fx 0x0. trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (806,999)-(986,1080), src_surface 0x16c9c8, src_rect (806,999)-(986,1080), flags 0x1000000, fx 0x0. trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (1097,734)-(1277,914), src_surface 0x16c9c8, src_rect (1097,734)-(1277,914), flags 0x1000000, fx 0x0. trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (860,481)-(1040,661), src_surface 0x16c9c8, src_rect (860,481)-(1040,661), flags 0x1000000, fx 0x0. trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (860,481)-(1040,661), src_surface 0x16c9c8, src_rect (860,481)-(1040,661), flags 0x1000000, fx 0x0. trace:ddraw:ddraw_surface7_Blt iface 0x16c160, dst_rect (1354,797)-(1534,977), src_surface 0x16c9c8, src_rect (1354,797)-(1534,977), flags 0x1000000, fx 0x0. ...
I think Wine, however, always flushes a complete new screen via OpenGL, as the game spends almost all of its time waiting for glFlush() to finish. I have verified that this is the case by applying the attached patch to the Mac driver code to unconditionally clamp the glFlush rate to 60Hz. This solves the speed issue, even at 1920x1080 (without the patch, the game is glacial even at 800x600). Obviously, the patch cannot be integrated in wine, since it occasionally discards the "last" blit to screen after a static scene change, leaving old data visible and no longer updating.
I previously posted about this issue (a long time ago) on wine-dev: https://www.winehq.org/pipermail/wine-devel/2015-February/106625.html . To answer some questions/suggestions from the end of that thread: a) the SkipSingleBufferFlushes registry key does not help (my system supports the GL_APPLE_flush_render extension) b) related to Henri Verbeet's suggestion that it may be related to wine possibly not implementing asynchronous ddraw blits: it's true that wine does not support this, but OTOH the game does not ask for them either: it calls ddraw_surface7_Blt rather than ddraw_surface7_BltFast (BltFast is documented on MSDN as always being asynchronous), and it does not set the DDBLT_ASYNC flag
The game offers a built-in ability to wait for vsync via its configuration file (set the VSync variable in $HOME/Documents/My Games/MajestyHD/MajXPrefs to "1"), but that only results in trace:ddraw:ddraw7_WaitForVerticalBlank iface 0x146750, flags 0x1, event 0x0. fixme:ddraw:ddraw7_WaitForVerticalBlank iface 0x146750, flags 0x1, event 0x0 stub!
I'm also not sure whether it would help, but looking at the ddraw log (which I will also attach -- it's a trace+ddraw,trace+d3d_draw log), I think it may since often there are several blits between the vsync waits.
Some possible approaches to tackle this issue may be: * handle small direct rects more efficiently * add support for waiting for VSync in ddraw
There is a demo of an older version of the game, but it can only run in 640x480 and there is no way to adjust the game speed via an in-game slider, and at least on my system the difference with and without my patch is not very visible there (http://www.cyberlore.com/Majesty/demo.htm )