The code itself isn't wrong but we're entirely missing the logic needed
to make it work. This leads to spontaneous crashes with video drivers and
various unity games.
CORE-17932
[ENG] Implement DirectDraw management in switch display mode functions
(e.g. resolution change, color depth, display frequency etc.):
- Switch DirectDraw instances between the two PDEVs (the current one and
the new one allocated by ourselves) by calling dxg!DxDdDynamicModeChange
function.
- Suspend them before and resume after the display mode switch, by calling
dxg!DxDdsuspendDirectDraw and dxg!DxDdResumeDirectDraw appropriately.
We currently don't have these functions implemented, but MS DXG has, so
it allows to properly manage DirectDraw PDEVs using this driver, similarly
to Windows.
My analysis confirms that these functions are always called in XP/2k3 on
display mode switch, even when there is no any DirectX app running at the
moment. Analyzing their prototypes show that my guesses are correct.
- Initialize hDev and dhpdev members for EDD_DIRECTDRAW_GLOBAL for newly
created surfaces, switch them during mode change and re-initialize after
it also. They are commonly used by DirectDraw stack.
In addition, enable DirectDraw for old and new PDEVs, by calling
dxg!DxDdEnableDirectDraw function.
[NTDDRAW] Additionally, fix usage of DirectDraw lock count in the PDEVOBJ
structure.
- Enable cDirectDrawDisableLocks member for storing its value, instead of
DxDd_nCount, which is marked as ROS-specific.
- Use it in win32k!DxEngGet/SetHdevData for getting/setting DirectDraw
count appropriately.
My analysis also shows that in Windows, the PDEVOBJ::cDirectDrawDisableLocks
method calls DxEngGetHdevData with type 8, which corresponds to our DxDd_nCount.
So there are no doubts that this member is used there.
- Rename DxEngGetHdevData_dd_count alias of type 8 to DxEngGetHdevData_dd_locks,
to match more accurately an actual member name. Update the enumeration
and fix all code parts appropriately.
All these changes allow to properly change display mode during executing
DirectDraw applications, when they try to switch in full-screen mode.
At least a bugcheck that happened before my changes, does no longer appear.
There are still some games that don't run correctly, as if there is no
3D acceleration (which actually exists). This requires further investigations.
This can be configured in registry with DefaultSettings.XPanning and
DefaultSettings.YPanning, which describe the real screen resolution.
DefaultSettings.XResolution and DefaultSettings.YResolution describe
the resolution of the virtual screen.
When changing current devmode, we must not only change ppdev->pdmwDev
pointer, but also update lots of other structures. This work is done by
PDEVOBJ_lChangeDisplaySettings.
CORE-18169
- do not try to remove ppdev from gppdevList if gppdevList is NULL
- do not check (and maybe change) gpmdev, as it should be done only in MDEVOBJ_vDestroy
- store the acceleration level in PDEVOBJ
- when searching a pdev, search a pdev with required acceleration level
- disable some functions when not at full acceleration level
(levels 3 and 5 are not implemented)
This function can create a MDEV for the whole display (maybe containing multiple
PDEVs), or update settings of a specific PDEV.
- call PDEVOBJ_lChangeDisplaySettings when switching to graphics mode.
- modify EngpGetPDEV to search requested PDEV only in current MDEV
This will be used (later) to store the list of all enabled display devices.
Add a global variable gpmdev (should really be stored in DISPLAYINFO structure)
Replace global variable gppdevPrimary by pmdev->ppdevGlobal.
- change first argument to be a PGRAPHICS_DEVICE instead of a device name
- add ldevtype (for now, only LDEV_DEVICE_DISPLAY is allowed)
- always pass a devmode if ldevtype is LDEV_DEVICE_DISPLAY
- insert the ppdev into gppdevList on success
- change callers to adapt them to new rules
- make it return a new allocated PDEVMODEW instead of a pointer into
existing PGRAPHICS_DEVICE (usefull when available display modes can
dynamically change: VirtualBox, RDP, ...)
- update all callers
- Change INIT_FUNCTION and INIT_SECTION to CODE_SEG("INIT") and DATA_SEG("INIT") respectively
- Remove INIT_FUNCTION from function prototypes
- Remove alloc_text pragma calls as they are not needed anymore
This helps when e.g. changing the resolution on the Dell Latitude D531,
which reports that it supports large resolutions (e.g. 1920x1440x32 and
others larger than 1024x768x32) but fails to apply these.
This usually happens because PDEVOBJ_pSurface(), and more precisely
ppdev->pldev->pfn.EnableSurface(), fails for these resolutions.
- PDEVOBJ_bSwitchMode(): Set the new video mode, or restore the original
one in case of failure + release the allocated ppdevTmp if previous
calls fail. Also unlock in reverse order of locking order.
- UserChangeDisplaySettings(): In case PDEVOBJ_pSurface() fails (but has
reverted the original video mode), we still need to refresh the
display since the display may have been messed up.