Custom mouse icon memory crash bug

I am having a very odd bug in my DesktopGL MG (3.8.0.1641) project that occasionally causes an out of memory crash when I try to set a custom mouse icon via MouseCursor.FromTexture2D(MouseCursorTarget, 0, 0).

I have not yet been able to locate the cause of this bug or a way to consistently reproduce it. It just happens sometimes after a while.

What I do is that I spriteBatch.Draw into a RenderTarget2D, and then pass that into the MouseCursor.FromTexture2D(). I suspect this is causing a memory leak somewhere, where I keep generating new textures which are not disposed, however, I cannot see where this could be happening.

Any ideas? What am I missing?

Here is a trace:

System.InvalidOperationException
HResult=0x80131509
Message=Failed to set surface for mouse cursor: CreateIconIndirect(): Not enough memory resources are available to process this command.

Source=MonoGame.Framework
StackTrace:
at Microsoft.Xna.Framework.Input.MouseCursor.PlatformFromTexture2D(Texture2D texture, Int32 originx, Int32 originy)

And here is a mock version of where I update the render target, which is called at every MG Draw():

public static RenderTarget2D MouseCursorTarget = new RenderTarget2D(_graphicsDevice, CursorWidth, CursorSize, false, _graphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);

public static void DrawCustomCursor() {
_graphicsDevice.SetRenderTarget(MouseCursorTarget);
_graphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true };
_graphicsDevice.Clear(Color.Transparent);
spriteBatch.Begin();
spriteBatch.Draw(<UI_TEXTURE>, , , Color.White, 0f, new Vector2(), SpriteEffects.None, 0);
spriteBatch.End();

_graphicsDevice.SetRenderTarget(null);
}

Try this:

Mouse.SetCursor(MouseCursor.FromTexture2D(MouseCursorTarget, 0, 0));

No render target needed.

pherbeas

Thank you for taking the time to look into this. However, I do not understand your suggestion!

What do you mean by “No render target needed.”? “MouseCursorTarget” is a RenderTarget2D instance, (a static member), otherwise what would I be rendering?

Could you please elaborate?

I solved it! I actually found that this issue was already encountered here (albeit with a different error message, hence I did not initially find it):

Basically MouseCursor.FromTexture2D(), creates a new MouseCursor instance, each of which has an internal Texture2D instance. So when I was calling this function I was basically creating new Texture2Ds, and the previous ones were never de-referenced and thus disposed, hence the memory leak. The solution was to keep track of the last custom MouseCursor, and call dispose on it before I created a new one:

public static MouseCursor customCursor; // a static instance of past custom Mouse cursors, so they can be disposed of if there is a new one so there are no memory leaks
…
if (customCursor != null) customCursor.Dispose();
customCursor = MouseCursor.FromTexture2D(MouseCursorTarget, 0, 0);
Mouse.SetCursor(customCursor);

2 Likes

Nice! This is good to know. I only use 1 custom cursor and set it in LoadContent() and forget about it.

Glad you found the answer!

pherbeas