Monogame для Windows Phone 8: черные текстуры после деактивации

Я столкнулся со странной проблемой в моем приложении monogame (3.1) для Windows Phone 8. Когда приложение деактивировано, а затем активировано, все текстуры становятся черными. Это произошло также после блокировки экрана (UserIdleDetectionMode включен).

Я проверил GraphicsDevice.IsDisposed, GraphicsDevice.IsContentLost, GraphicsDevice.ResourcesLost, но все выглядит хорошо. Я реализовал перезагрузку всех своих текстур в событиях Activated и Unobscured, но полная перезагрузка текстуры занимает слишком много времени. В то же время в Marketplace я вижу одноигровые приложения, легко обрабатывающие функцию дезактивации-активации. Более того, это же приложение для windows phone 7, написанное на xna, восстанавливает очень быстро. Что я делаю не так с моногамой? Мое приложение основано на одноигровом шаблоне WP8.

Обновить:

Только что обнаружили, что все текстуры, загруженные через Content.Load (...), восстанавливаются очень быстро. Но все мои текстуры написаны от руки: я загружаю файл из TileContainer, распаковываю его, читаю его данные с помощью ImageTools, создаю Texture2D и устанавливаю его пиксели с загруженными данными. Файлы JPEG также отображаются в RenderTarget2D как BGR565, чтобы использовать пространство. Более того, я широко использую RenderTarget2D для рендеринга текстовых меток с тенями, композиций времени выполнения спрайтов и так далее. Похоже, что Monogame просто не хочет восстанавливать изображения, загруженные не Content.Load. Продолжать расследование...

2 ответа

Решение

Согласно моногамным разработчикам потерянные текстуры - нормальная ситуация. Я сделал полную перезагрузку текстуры в событии GraphicsDevice.DeviceReset. Чтобы это работало быстро, я реализовал загрузку из несжатых файлов xnb. Это довольно просто, если в этом формате есть только значения пикселей. Это единственное решение.

Вот как читать с несжатого 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;
}

Я только что получил ответ от Тома Спилмана на форумах Monogame, и очевидно, что содержимое Content.Load восстанавливается нормально, и другие данные должны быть повторно инициализированы программой. Что вы можете сделать, это подключиться к событию GraphicsDevice.DeviceResetting, чтобы получить уведомление, когда происходит этот сброс.

Другие вопросы по тегам