I've been using CocosSharp successfully with Monogame 3.6. However, when upgrading to 3.7 (or the latest 3.8 dev build), the following code is now corrupting loaded texture data
var b = new Color[rt.Texture.PixelsHigh * rt.Texture.PixelsWide];
rt.Texture.XNATexture.GetData<Color>(b);
It appears, rather than just reading out the data, to completely overwrite the texture with a section from a corner of the current screen.
To emphasise: this isn't just a case of it returning the wrong data. The texture being read becomes corrupted and overwritten entirely.
It seems the actual data being returned is correct. However, calling SetData on the texture straight afterwards has no effect.
I can confirm that this occurs on iOS as well.
Having same issue here using vanilla Monogame Android project, nothing else. Calling someTexture.GetData
For clarity, although #6727 was closed, the root issue turned out to be simply reading from the texture on Android caused the source texture to disappear. It's possible in the case of this "disappearing" to actually be a copy of the corner of the screen, as detailed on this Issue number (6506).
I've a possible work-around for the moment.
In my case, I'm processing a PNG just loaded, in preparation for use - so in my case, a one liner of inconvenience:
img = new Texture2D(graphicsDevice, img.Width, img.Height);
img.SetData<Color>(colourData);
where img is a Texture2D that you've just called the "img.GetData
Put simply, if the texture is corrupted, then create a new texture! You've got the Color[] data to do so, and the original texture can tell you the width and height the replacement texture needs to be.
This one line (in the right place) got my code working - until there's an official fix.
I've reproduced this issue with android emulator and looked into it a bit.
It seems this line is the one to blame:
https://github.com/MonoGame/MonoGame/blob/142ea8393e5e316ad88c5ed9a7c40554a02d9e64/MonoGame.Framework/Graphics/Texture2D.OpenGL.cs#L213
If it is replaced with
C#
GL.DeleteFramebuffers(1, ref framebufferId);
then everything works fine and texture isnt corrupted by GetData call.
On a glance, the difference between deleting the frame buffer and disposing the frame buffer is that the former is immediate, whereas disposal is delayed to the next frame.
So deleting will detach the frame buffer from the texture immediately. However, since glReadPixels is synchronous (as per the spec) it is unclear why an operation AFTER it would affect client memory.
Perhaps the GLES implementation is doing some trickery and using a pixel buffer object under the hood?
Attaching a texture to a frame buffer won't work properly if the texture was not bound yet at some point. I haven't gone and traced this, but it looks like the Monogame implementation would have bound it.
Most helpful comment
I've reproduced this issue with android emulator and looked into it a bit.
It seems this line is the one to blame:
https://github.com/MonoGame/MonoGame/blob/142ea8393e5e316ad88c5ed9a7c40554a02d9e64/MonoGame.Framework/Graphics/Texture2D.OpenGL.cs#L213
If it is replaced with
C# GL.DeleteFramebuffers(1, ref framebufferId);then everything works fine and texture isnt corrupted by GetData call.