iXit / Mesa-3D

Please use official https://gitlab.freedesktop.org/mesa/mesa/ !
https://github.com/iXit/Mesa-3D/wiki
66 stars 13 forks source link

World of Warships cursor not rendering #197

Closed Oblit03 closed 6 years ago

Oblit03 commented 8 years ago

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

if (!This->cursor.software)
    This->cursor.software = FALSE; //ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;

Or this:

if (This->cursor.software)
    This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;

Or this:

/*
if (!This->cursor.software)
    This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
*/

Forcing software cursor also works: device9.c line 278 This->cursor.software = TRUE;

Files: Log Trace

Reverting commit a306847 does not fix this bug.

axeldavy commented 8 years ago

This is quite weird

Oblit03 commented 8 years ago

!!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.

Oblit03 commented 8 years ago

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);
axeldavy commented 8 years ago

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.

axeldavy commented 8 years ago

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.

axeldavy commented 8 years ago

Is the game supposed to keep system cursor ?

axeldavy commented 8 years ago

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.

Oblit03 commented 8 years ago

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.

axeldavy commented 8 years ago

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.

siro20 commented 8 years ago

Yes it need more tests. Should be simple to merge when ready.

Altosk commented 7 years ago

I've been playing this game the above patch works with no changes in WoW 7.1.5 and 1.12.1 .

axeldavy commented 6 years ago

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.