OpenRA / OpenRA

Open Source real-time strategy game engine for early Westwood games such as Command & Conquer: Red Alert written in C# using SDL and OpenGL. Runs on Windows, Linux, *BSD and Mac OS X.
https://www.openra.net
GNU General Public License v3.0
14.56k stars 2.65k forks source link

Hardware cursor option gets disabled and results in hidden cursor #10172

Open pi99y opened 8 years ago

pi99y commented 8 years ago

I noticed some time ago that the "HW cursor" option rets ~randomly disabled. In IRC logs I saw that this is a "fallback" thing if "problems" are detected. (What problems exactly?)

It wasn't a problem for me before, since it didn't affect anything. Now my cursor disappears and stays hidden until I reenable the option and restart OpenRA (which is a pain since I can't see the cursor).

It seems that it is maybe triggered by Alt-Tabbing (switching between windows). Also it seems that it only happens with pseudo-fullscreen and not with the fullscreen. (But that's not a great alternative since capturing software seems to work only with pseudo)

EDIT: Nope, it also happens in "fullscreen" and without "Alt-tabbing".

What others say: :)

antares79: open the ticket against your gpu driver, not against us ... hamb: the hw cursor disabling itself? hamb: swear i have that too ... jaZz_KCS: IF the focus is lost, apparently jaZz_KCS: I had the same problem

pi99y commented 8 years ago

Is there (or should there be) an option (like command line parameter) to force HW cursors so I could always force that option? This "fallback" thing happens at least twice in 10 tries...

pchote commented 8 years ago

@pi99y if you want the game to crash, sure ;)

The fallback applies when the game detects that the lower level cursor code (in SDL / Windows / your drivers) has crapped itself and is about to crash. We have full control over the software cursors, so fall back to those as a recovery option.

pi99y commented 8 years ago

Thanks for the explanation @pchote

Oh well... that's no good then :) Could it be that OpenRA causes drivers to act ~bad? I haven't seen any abnormalities in with other software/games.

Perhaps others with the same problem (hamb, @jaZzKCS) should report what driver / card they are using... Is it an Intel HD graphics only problem?

RoosterDragon commented 8 years ago

I have also encountered this on Intel HD, so it's a possibility.

If you grab your debug logs when this happens, it should contain a line: Failed to initialize hardware cursors. Falling back to software cursors. followed by Error was: ....

If you could let us know your error message, that'd be super. If I run into the problem again (haven't had it for ages) I'll try and grab my logs, too.

pi99y commented 8 years ago

OK, here's my debug.log I kept restarting OpenRA (current playtest 20151129) until HW cursor got disabled (and the cursor disappeared). I cleared all logs before each run, so this log should contain just errors from this instance.

BTW: It's interesting that it mentions failing to load a map. I have shellmap disabled (black screen) and I never clicked elsewhere other than the options... What's with the forward slash "/" before the "ra" folder? Even with that it does resolve into the right directory, but the map is indeed corrupted = 0 bytes.

Failed to load map: [C:\Users\piggy\Documents\OpenRA\maps/ra\The_Combat_Island-2-3.oramap, User] Details: System.InvalidOperationException: Required file map.yaml not present in this map at OpenRA.Map.AssertExists(String filename) at OpenRA.Map..ctor(String path) at OpenRA.MapCache.LoadMaps() Failed to initialize hardware cursors. Falling back to software cursors. Error was: Failed to create hardware cursor sell-blocked Found 35 domains for movement class 699 on map Desert Shellmap. Found 3 domains for movement class 4096 on map Desert Shellmap. --Tick: 1 (net) ... ... and so on, full file here: http://s000.tinyupload.com/index.php?file_id=94716802187315348653

RoosterDragon commented 8 years ago

Unfortunately my changes from #8001 mean the actual error message we need is no longer getting logged out (it's buried inside the inner exception - doh!)

pi99y commented 8 years ago

Can you maybe create a debug version (that would log it) for me to test? :)

RoosterDragon commented 8 years ago

I did some debugging on my system. If I force the game to try and load hardware cursors 1000s of times, I get the same error as I reported in #8001 (even though we now retry a few times).

I figure we can up the retry count to something more generous, our only other option is to figure out the actual cause of the bug and report it to the right people.

pi99y commented 8 years ago

Until this is fixed: Could the fallback feature be set so that it disables HW cursor just for that session so that it will try again when you re-run the game please? Now, each time it happens I need to reset the options (harder when you don't see the cursor) plus restart the game. Thank you.

pi99y commented 8 years ago

With the new "patch" in #10196 (which works) the error for failing is logged as:

Failed to initialize hardware cursors. Falling back to software cursors. Error was: Failed to create hardware cursor sell-blocked - Failed to create cursor: >CreateIconIndirect(): The parameter is incorrect.

RoosterDragon commented 8 years ago

That's the same error I was seeing.

Unfortunately, just retrying more times isn't sufficient to fix the problem - so we're still going to have to work out the root cause.

Aneyrin commented 8 years ago

I have the same problem with cursor on my Intel HD graphics. The only way to avoid this bug is switching to windowed mode.

pi99y commented 8 years ago

For me it happens occasionally no matter the display mode (full/pseudo/windowed). But now since the HW cursor settings won't get disabled/forgotten I just restart the game and it's fine again.

yaaaaa commented 8 years ago

in early builds of Windows 10 OR early builds of OpenRA it was same way (to see cursor i must restatr game several times). But Now (in lastest builds of Windows and/or OpenRA) this troblem is gone.

pi99y commented 8 years ago

Since the new playtest (20160403) cursor fails and is hidden EVERY time if I have "pseudo-fullscreen" enabled. "fullscreen" seems to work.

The logged error is: Failed to initialize hardware cursors. Falling back to software cursors. Error was: Failed to create hardware cursor guard-minimap - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

daiplusplus commented 7 years ago

Here's the inner exception I got:

InvalidDataException
Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.
   at OpenRA.Platforms.Default.Sdl2GraphicsDevice.SDL2HardwareCursor..ctor(Size size, Byte[] data, int2 hotspot) in C:\\Git\\OpenRA\\OpenRA.Platforms.Default\\Sdl2GraphicsDevice.cs:line 142
   at OpenRA.Platforms.Default.Sdl2GraphicsDevice.CreateHardwareCursor(String name, Size size, Byte[] data, int2 hotspot) in C:\\Git\\OpenRA\\OpenRA.Platforms.Default\\Sdl2GraphicsDevice.cs:line 96

This calls into SDL's SDL_CreateColorCursor, which on Windows is defined as WIN_CreateCursor which is mirrored here: https://github.com/spurious/SDL-mirror/blob/d3f9978231577841304e160af50813c5e999c198/src/video/windows/SDL_windowsmouse.c

The problem call is on line 138 where it calls hicon = CreateIconIndirect(&ii); which is the actual Win32 function call that fails (because hicon == NULL which causes it to return NULL).

That the call to CreateIconIndirect fails with "The parameter is incorrect" means the ICONINFO ii structure is not being initialized correctly, which happens between lines 124 and 138 in the SDL function. I note that there is no error-checking code to see if CreateDIBSection or CreateBitmap fails, and I suspect those functions are failing for some race-condition. I'd need to set-up a native debugger and step-in to SDL to find out what's going on, which I don't have the time for currently, unfortunately.

In summary: this may be a bug in SDL.

rob-v commented 7 years ago

HW cursor test on my NB with Intel HD + Nvidia, Windowed mode. It looks like OpenRA issue, not general issue. Nvidia: 7/10 success Intel: 7/10 success when it fails my cursor is jerky. Since I realize this issue, I restart OpenRA, because it isn't smooth and I am even afraid that it is causing lag. The issue is that there is no indication of this 30% chance failure. I would welcome at least an icon in one of corners on main screen to indicate I use SW cursor instead of HW cursor. Would be addition of such indication accepted?

daiplusplus commented 7 years ago

Note, you don't need to restart OpenRA to try to get a hardware cursor. Instead click on the "Mods" button and that always fixes it for me.

dragunoff commented 4 years ago

I'm getting this kind of errors occasionally:

Failed to initialize hardware cursors. Falling back to software cursors.
Error was: Failed to create hardware cursor `attackoutsiderange-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.
Failed to initialize hardware cursors. Falling back to software cursors.
Error was: Failed to create hardware cursor `enter` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.
Failed to initialize hardware cursors. Falling back to software cursors.
Error was: Failed to create hardware cursor `move-rough` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.
daiplusplus commented 4 years ago

I can also still reproduce the issue using Release 20191117 - there's no obvious cause, pattern or reason for it - but because the Mods button is gone I have to quit and restart the game a few times before I get a hardware cursor.

I'm curious why it's temperamental - the SDL/Win32 error message about parameter validation makes it seem like a deterministic issue.

pchote commented 4 years ago

While working on #17517 I noticed that we tended to fail on cursors that have weird frame sizes. Historically, Windows was very picky about its icon and cursor sizes - requiring things to be a multiple of 8 (24, 32, 48, etc px).

Testing now on Windows, I find that previous bleed d2k would reliably fail to load hardware cursors. On #17517, which is rounding the surface size to a multiple of 8, it seems to be reliably (fingers crossed) working. Lets see if this holds up.

Update: unfortunately this did not solve the problem.

pchote commented 3 years ago

As part of testing #17837 i did a quick test replacing SDL with GLFW, and this problem remained. This suggests that it is not related to SDL, but something lower level and probably not fixable in Windows. It may be some internal resource exhaustion related to the fact that we are creating a few hundred cursors at once.

19387 has removed the global fallback to software cursors so this problem should now at least be significantly less noticeable.

daiplusplus commented 3 years ago

@pchote

It may be some internal resource exhaustion related to the fact that we are creating a few hundred cursors at once.

Why is that necessary though? The game has fewer than a 100 cursors.

daiplusplus commented 3 years ago

FWIW, here's my stdout log when I cloned the repo, build my local copy from bleed (commit b3b10729cd):

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:07.88
Build succeeded.
Downloading IP2Location GeoIP database.
Press enter to continue.

C:\git\clones\OpenRA>
C:\git\clones\OpenRA>launch-game Game.Mod=ra
Platform is Windows
Engine version is {DEV_VERSION}
Runtime: .NET CLR 5.0.7
Using SDL 2 with OpenGL (ANGLE) renderer
Desktop resolution: 3840x2160
No custom resolution provided, using desktop resolution
Using resolution: 3840x2160
Using window scale 1.00
OpenGL renderer: ANGLE (Radeon RX 5500 XT Direct3D11 vs_5_0 ps_5_0)
OpenGL version: OpenGL ES 3.0.0 (ANGLE 2.1.0.ea8043b73f93)
Using default sound device
Internal mods:
        all: All mods ({DEV_VERSION})
        cnc: Tiberian Dawn ({DEV_VERSION})
        d2k: Dune 2000 ({DEV_VERSION})
        modcontent: Mod Content Manager ({DEV_VERSION})
        ra: Red Alert ({DEV_VERSION})
        ts: Tiberian Sun ({DEV_VERSION})
External mods:
        cnc-release-20210321: Tiberian Dawn (release-20210321)
        d2k-release-20210321: Dune 2000 (release-20210321)
        ra-release-20210321: Red Alert (release-20210321)
        cnc-release-20200503: Tiberian Dawn (release-20200503)
        ra-{DEV_VERSION}: Red Alert ({DEV_VERSION})
Loading mod: ra
Failed to initialize hardware cursor for c4-minimap.
Error was: Failed to create hardware cursor `c4-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for guard.
Error was: Failed to create hardware cursor `guard` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for guard-minimap.
Error was: Failed to create hardware cursor `guard-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for capture.
Error was: Failed to create hardware cursor `capture` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for capture.
Error was: Failed to create hardware cursor `capture` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for capture.
Error was: Failed to create hardware cursor `capture` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for capture-minimap.
Error was: Failed to create hardware cursor `capture-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for capture-minimap.
Error was: Failed to create hardware cursor `capture-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for capture-minimap.
Error was: Failed to create hardware cursor `capture-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for heal.
Error was: Failed to create hardware cursor `heal` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for heal.
Error was: Failed to create hardware cursor `heal` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for heal.
Error was: Failed to create hardware cursor `heal` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for heal.
Error was: Failed to create hardware cursor `heal` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for heal-minimap.
Error was: Failed to create hardware cursor `heal-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability.
Error was: Failed to create hardware cursor `ability` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for ability-minimap.
Error was: Failed to create hardware cursor `ability-minimap` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-all.
Error was: Failed to create hardware cursor `joystick-all` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-t-blocked.
Error was: Failed to create hardware cursor `joystick-t-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-tr-blocked.
Error was: Failed to create hardware cursor `joystick-tr-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-r-blocked.
Error was: Failed to create hardware cursor `joystick-r-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-br-blocked.
Error was: Failed to create hardware cursor `joystick-br-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-b-blocked.
Error was: Failed to create hardware cursor `joystick-b-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-bl-blocked.
Error was: Failed to create hardware cursor `joystick-bl-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-l-blocked.
Error was: Failed to create hardware cursor `joystick-l-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for joystick-tl-blocked.
Error was: Failed to create hardware cursor `joystick-tl-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy.
Error was: Failed to create hardware cursor `deploy` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for deploy-blocked.
Error was: Failed to create hardware cursor `deploy-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench.
Error was: Failed to create hardware cursor `goldwrench` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for goldwrench-blocked.
Error was: Failed to create hardware cursor `goldwrench-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for nuke.
Error was: Failed to create hardware cursor `nuke` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-select.
Error was: Failed to create hardware cursor `chrono-select` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for chrono-target.
Error was: Failed to create hardware cursor `chrono-target` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell.
Error was: Failed to create hardware cursor `sell` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell-blocked.
Error was: Failed to create hardware cursor `sell-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair.
Error was: Failed to create hardware cursor `repair` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for repair-blocked.
Error was: Failed to create hardware cursor `repair-blocked` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

Failed to initialize hardware cursor for sell2.
Error was: Failed to create hardware cursor `sell2` - Failed to create cursor: CreateIconIndirect(): The parameter is incorrect.

C:\git\clones\OpenRA>git status
On branch bleed
Your branch is up to date with 'origin/bleed'.

nothing to commit, working tree clean

C:\git\clones\OpenRA>git branch -v
* bleed b3b10729cd Remove ServerExternalMod from OrderManager

C:\git\clones\OpenRA>

HTH.

I'm fiddling with SDL's WIN_CreateCursor and I've reimplemented WIN_CreateCursor in C# to see what's going wrong.

daiplusplus commented 3 years ago

So... my reimplementation of WIN_CreateCursor in all-C# (with some ugly call-outs to msvcrt.dll for malloc/calloc/free-compatibility with SDL2 seems stable - it never fails for me and OpenRA works flawlessly.

I'll post my code in a moment.

(Annoyingly, because I can't get my code to fail I can't find out why SDL is failing - but I did notice that sometimes the HICON and some other GDI handles (which are typed as void*) had values over 2^32 - and the fact this is non-deterministic behaviour in SDL suggests some memory isn't being zeroed-out correctly somewhere - or if they're using incorrect struct definitions.

daiplusplus commented 3 years ago

Here's my code: https://github.com/OpenRA/OpenRA/compare/bleed...Jehoel:dev/2021-06-21-cursor-trouble (I included SDL_windowsmouse.c for reference)

As Sod's law would have it, right now (since about 5 minutes ago) whenever I run OpenRA the SDL code works fine and CreateIconIndirect never fails. 🤦‍♂️ (I do want to assert that my code does work because when I was writing it it was only invoked after the original SDL code failed 3 times in a row instead of throwing an exception as it does in the current bleed branch)

I'd appreciate it if someone else could validate my code.

Note that I'm not necessarily advocating using my SDL reimplementation code in OpenRA just yet - I still feel uneasy directly calling calloc from C#. I don't know if there's any stuff going on in SDL at runtime that might use a different allocator, etc.


If the issue is just a dodgy sizeof constant in SDL then it should be straightforward to apply a binary patch to the bundled SDL2.dll to correct it, fwiw - rather than recompiling it from source.

abcdefg30 commented 3 years ago

The implementation seems to work. I noticed something interesting though: If a cursor fails to create and we throw an exception all subsequent cursors aren't created either. With https://github.com/OpenRA/OpenRA/compare/bleed...abcdefg30:testCursors only one(!) cursor fails to create on my system (however, not always the same cursor, but consistently only a single one, not more not less). Your implementation also only seems to need to fallback once to the C# implementation.

daiplusplus commented 3 years ago

@abcdefg30 The implementation seems to work. I noticed something interesting though: If a cursor fails to create and we throw an exception all subsequent cursors aren't created either.

Exceptions shouldn't be used for non-exceptional failures. Given that cursor-creation-failure is a known-issue and currently non-exceptional it shouldn't result in a throw. But yeah... changing the return-type to a tuple that indicates failure is a breaking change...

Your implementation also only seems to need to fallback once to the C# implementation.

My experience differs from yours - in my case I saw my code was being invoked hundreds of times (during the times when I could reproduce it). (Though I'll concede that I did fiddle with things for a while, it's possible that right now my code behaves as you describe, but that isn't how I remember it).

I'll restate that the fact it's apparently nondeterministic suggests it's either something tied to hardware (are our graphics cards seated correctly in their slots? no bad RAM sticks? not operating a computer close to a national physics laboratory?) or a memory issue.

I'm wondering if another approach could be used: aren't there some debug/compat functions or flags in Windows that can be used to ensure all pages are zeroed when allocated to the process?