0
votes

My engine was recently converted to run with SDL2 for input, and video. However, I am having a hard time getting the resolution mode list building working correctly. I did study the Migration Guide for SDL2, as well as heavily research links -- I am not sure how to go about it, several failed attempts later.

So, for starters, I have a file, called i_video.cc, that handles SDL2 video code. 99% of the engine runs in OpenGL, so SDL is only there to initialize the window and set any variables.

So, here was the old way of grabbing resolution into our screen mode class. For reference, the screen mode class is defined in r_modes.cc.

With that said, here is the old SDL1-based code that builds the screen mode list, that I cannot, for the LIFE of me, get running under SDL2. This code starts at line 190 in i_video.cc. For reference, the old code:

// -DS- 2005/06/27 Detect SDL Resolutions
    const SDL_VideoInfo *info = SDL_GetVideoInfo();
    SDL_Rect **modes = SDL_ListModes(info->vfmt,
        SDL_OPENGL | SDL_DOUBLEBUF | SDL_FULLSCREEN);
    if (modes && modes != (SDL_Rect **)-1)
    {
        for (; *modes; modes++)
        {
            scrmode_c test_mode;
            test_mode.width = (*modes)->w;
            test_mode.height = (*modes)->h;
            test_mode.depth = info->vfmt->BitsPerPixel;  // HMMMM ???
            test_mode.full = true;
            if ((test_mode.width & 15) != 0)
                continue;
            if (test_mode.depth == 15 || test_mode.depth == 16 ||
                test_mode.depth == 24 || test_mode.depth == 32)
            {
                R_AddResolution(&test_mode);
            }
        }
    }
    // -ACB- 2000/03/16 Test for possible windowed resolutions
    for (int full = 0; full <= 1; full++)
    {
        for (int depth = 16; depth <= 32; depth = depth + 16)
        {
            for (int i = 0; possible_modes[i].w != -1; i++)
            {
                scrmode_c mode;
                mode.width = possible_modes[i].w;
                mode.height = possible_modes[i].h;
                mode.depth = depth;
                mode.full = full;
                int got_depth = SDL_VideoModeOK(mode.width, mode.height,
                    mode.depth, SDL_OPENGL | SDL_DOUBLEBUF |
                    (mode.full ? SDL_FULLSCREEN : 0));
                if (R_DepthIsEquivalent(got_depth, mode.depth))
                {
                    R_AddResolution(&mode);
                }
            }
        }
    }

It is commented out, and you can see the SDL2 code above it that sets SDL_CreateWindow. The video is just fine in-game, but without resolution building, we cannot get screen-resolution changes without passing command-line arguments first before the program loads. I wish they left SOME kind of compatibility layer, because it seems SDL2 has a slight learning curve over the way I've always handled this under SDL1.

I know that ListModes and VideoInfo no longer exist, and I've tried replacing them with equivalent SDL2 functions, such as GetDisplayModes, but the code just doesn't work correctly. I am not sure how I'm supposed to do this, or if r_modes.cc just needs to be completely refactored, but all I need it to do is grab a list of video modes to populate my scrmode_c class (in r_modes.cc).

When I try to replace everything with SDL2, I get an invalid cast from SDL_Rect* to SDL_Rect**, so maybe I am just doing this all wrong. Several months I've spent trying to get it working, and it just doesn't want to. I don't care much about setting bits-per-pixel, as modern machines can just default to 24 now and we don't need any reason to set it to 16 or 8 anymore (nowadays, everyone has an OpenGL card that can go above 16-bit BPP) ;)

Any advice, help...anything at this point would be greatly appreciated =)

Thank you! -Coraline

1
Where's the attempt using SDL_GetDisplayMode() that gives you the cast errors?genpfault
I'm trying to find that code through the history but it doesn't seem to be there now (I think I removed it out of frustration..). Essentially, I had called SDL_GetDisplayMode() instead of SDL_ListModes, and instead of SDL_GetVideoInfo I called a SDL2 function for that. But I remember there was some sort of SDL_Rect casting issue that I was running into while trying to get it working... :/Cora
SDL2 is realy good for having a GL context on any platform, exept for transparency, so try harder...j-p

1 Answers

1
votes

Use a combination of SDL_GetNumDisplayModes and SDL_GetDisplayMode, then push these back into a vector of SDL_DisplayMode.

std::vector<SDL_DisplayMode> mResolutions;

int display_count = SDL_GetNumVideoDisplays();

SDL_Log("Number of displays: %i", display_count);

for (int display_index = 0; display_index <= display_count; display_index++)
{
    SDL_Log("Display %i:", display_index);

    int modes_count = SDL_GetNumDisplayModes(display_index);

    for (int mode_index = 0; mode_index <= modes_count; mode_index++)
    {
        SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };

        if (SDL_GetDisplayMode(display_index, mode_index, &mode) == 0)
        {
            SDL_Log(" %i bpp\t%i x %i @ %iHz",
                SDL_BITSPERPIXEL(mode.format), mode.w, mode.h, mode.refresh_rate);

            mResolutions.push_back(mode);
        }
    }
}