Question

I've faced a strange issue in my monogame (3.1) windows phone 8 app. When app is deactivated and then activated all textures become black. This happened also after the lock screen (UserIdleDetectionMode is enabled).

I've checked GraphicsDevice.IsDisposed, GraphicsDevice.IsContentLost, GraphicsDevice.ResourcesLost but everything looks ok. I've implemented reload of all my textures on Activated and Unobscured events, but full texture reload takes too much time. In the same time on Marketplace I see monogame apps easily handling desactivate-activate. Moreover, the same app for windows phone 7 written on xna, restores very quickly. What do I do wrong with monogame? My app is based on monogame WP8 template.

Update:

Just have found out that all textures which loaded via Content.Load(...) are restored very quickly. But all my textures are written by a hand: I load a file from TileContainer, unpack it, read its data with ImageTools, create Texture2D and set its pixels with loaded data. Jpeg files also are rendered to RenderTarget2D as BGR565 to consume space. Moreover I widely use RenderTarget2D for rendering text labels with shadows, sprite runtime compositions and so on. So it looks like that Monogame just don't want to restore images loaded not by Content.Load. Continue investigating...

Was it helpful?

Solution 2

According to monogame devs lost textures is a normal situation. I've made full texture reload in GraphicsDevice.DeviceReset event. To make it work fast I've implemented load from xnb uncompressed files. It's pretty simple as long as this format just have pixel values in it. This is the only solution.

Here's how to read from uncompressed xnb:

private static Texture2D TextureFromUncompressedXnbStream(GraphicsDevice graphicsDevice, Stream stream)
{
    BinaryReader xnbReader = new BinaryReader(stream);
    byte cx = xnbReader.ReadByte();
    byte cn = xnbReader.ReadByte();
    byte cb = xnbReader.ReadByte();
    byte platform = xnbReader.ReadByte();

    if (cx != 'X' || cn != 'N' || cb != 'B')
        return null;

    byte version = xnbReader.ReadByte();
    byte flags = xnbReader.ReadByte();

    bool compressed = (flags & 0x80) != 0;
    if (version != 5 && version != 4)
        return null;
    int xnbLength = xnbReader.ReadInt32();
    xnbReader.ReadBytes(0x9D);//skipping processor string
    SurfaceFormat surfaceFormat = (SurfaceFormat)xnbReader.ReadInt32();
    int width = (xnbReader.ReadInt32());
    int height = (xnbReader.ReadInt32());
    int levelCount = (xnbReader.ReadInt32());
    int levelCountOutput = levelCount;

    Texture2D texture = texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color);

    for (int level = 0; level < levelCount; level++)
    {
        int levelDataSizeInBytes = (xnbReader.ReadInt32());
        byte[] levelData = xnbReader.ReadBytes(levelDataSizeInBytes);
        if (level >= levelCountOutput)
            continue;
        texture.SetData(level, null, levelData, 0, levelData.Length);
    }
    xnbReader.Dispose();
    return texture;
}

OTHER TIPS

I just got a response from Tom Spillman in the Monogame forums and apparently the Content.Load stuff is restored normally and other data needs to be reinitialized by the program. What you can do is hook up to GraphicsDevice.DeviceResetting event to get notified when this reset is taking place.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top