Closed Oblit03 closed 6 years ago
This is quite weird
!!CORRECTION!! The above workarounds do still work...
Changing the following, without the above workarounds, also works:
wine/dlls/d3d9-nine/present.c:549
SetCursor(bShow ? This->hCursor : NULL);
to
SetCursor(bShow ? TRUE : NULL);
All of the above workarounds, except for forcing software cursor, break the cursor in Supreme Commander (not rendered).
This problem persists even with D3D_ALWAYS_SOFTWARE=1
.
The following code fixes the cursor bug in WoWS without breaking SC: wine/dlls/d3d9-nine/present.c:549
if (This->hCursor)
SetCursor(bShow ? This->hCursor : NULL);
Perhaps the code
if (cursor)
DestroyCursor(This->hCursor);
This->hCursor = cursor;
should be
if (cursor) {
DestroyCursor(This->hCursor);
This->hCursor = cursor;
}
EDIT: while it would be safer, it's probably not that.
It looks like our code is buggy, and if you call NineDevice9_ShowCursor to show the cursor, whereas you were already showing the cursor (and didn't change it), the we call SetCursor with a This->hCursor that wasn't filled.
Is the game supposed to keep system cursor ?
I think the correct fix is /* if bShow, but no cursor given yet, keep displaying system cursor */ if (!bShow || this->hCursor) SetCursor(bShow ? This->hCursor : NULL);
The other solution is in Mesa change This->cursor.visible = bShow && (This->cursor.hotspot.x != -1); if (!This->cursor.software) This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
by
This->cursor.visible = bShow && (This->cursor.hotspot.x != -1); if (!This->cursor.software && This->cursor.visible != old) This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
Both should work, but are not strictly equivalent. We have to choose.
Results:
This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
if (!This->cursor.software && This->cursor.visible != old)
This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
Cursor is shown in WoWS but not in Supreme Commander (SC works fine without these changes).
if (cursor) {
DestroyCursor(This->hCursor);
This->hCursor = cursor;
}
No changes.
/* if bShow, but no cursor given yet, keep displaying system cursor */
if (!bShow || This->hCursor)
SetCursor(bShow ? This->hCursor : NULL);
Cursor is shown in both WoWS and Supreme Commander.
I have no idea what cursor the game should use, but it is the only game I've tested that has this problem.
siro, do you agree with the wine patch ?
I think we cannot put it in the for_upstream_staging branch, we need more testing for that patch.
Yes it need more tests. Should be simple to merge when ready.
I've been playing this game the above patch works with no changes in WoW 7.1.5 and 1.12.1 .
I think the problem with
This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
if (!This->cursor.software && This->cursor.visible != old)
This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
Is that the application can do calls to the cursor api outside d3d.
We have applications like World of Warships which probably call SetCursor one time at init outside d3d, and thus we must not overwrite their SetCursor call when no cursor has been given to d3d.
However what may be happening with Supreme Commander is that it uses a d3d cursor, then uses manually SetCursor, to hide the cursor, then switches to d3d cursor again. With the above code, for us the cursor is still visible and thus we don't call SetCursor again.
Thus we have to be especially careful about these outside of d3d calls.
I think the following patch is the best way to handle the approach:
This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
if (!This->cursor.software && This->cursor.hotspot.x != -1)
This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
That is until we have any cursor given ((This->cursor.hotspot.x set to -1), everything is noop. However when there has been a cursor given, pass everything to SetCursor.
I'll push an equivalent patch. Please reopen if any of the two mentionned games has any issue.
The cursor shows briefly during loading (flashes in for about half a second) and then disappears. It does not render in-game in fullscreen or windowed mode.
This bug is not present with wined3d.
Changing the following code causes the cursor to render correctly:
device9.c lines 733-734
Or this:
Or this:
Forcing software cursor also works: device9.c line 278
This->cursor.software = TRUE;
Files: Log Trace
Reverting commit
a306847
does not fix this bug.