SDL1 -> 使用自定义屏幕模式类构建 SDL2 分辨率列表

Posted

技术标签:

【中文标题】SDL1 -> 使用自定义屏幕模式类构建 SDL2 分辨率列表【英文标题】:SDL1 -> SDL2 resolution list building with a custom screen mode class 【发布时间】:2016-06-22 20:59:53 【问题描述】:

我的引擎最近被转换为使用 SDL2 运行输入和视频。但是,我很难让分辨率模式列表构建正常工作。我确实研究了 SDL2 的迁移指南,以及大量研究链接——我不知道该怎么做,后来几次尝试都失败了。

所以,对于初学者来说,我有一个名为i_video.cc 的文件,用于处理 SDL2 视频代码。 99% 的引擎在 OpenGL 中运行,因此 SDL 仅用于初始化窗口和设置任何变量。

所以,这是在我们的屏幕模式类中获取分辨率的旧方法。供参考,屏幕模式类在r_modes.cc中定义。

话虽如此,这里是构建屏幕模式列表的旧的基于 SDL1 的代码,我终生无法在 SDL2 下运行。此代码从 i_video.cc 的第 190 行开始。供参考,旧代码:

// -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);
                
            
        
    

它被注释掉了,你可以看到它上面设置 SDL_CreateWindow 的 SDL2 代码。视频在游戏中很好,但如果没有分辨率构建,我们无法在程序加载之前不先传递命令行参数来更改屏幕分辨率。我希望他们留下某种兼容层,因为与我一直在 SDL1 下处理的方式相比,SDL2 似乎有一点学习曲线。

我知道 ListModes 和 VideoInfo 不再存在,我尝试将它们替换为等效的 SDL2 函数,例如 GetDisplayModes,但代码无法正常工作。我不确定我应该怎么做,或者如果 r_modes.cc 只需要完全重构,但我需要做的就是获取视频模式列表来填充我的 scrmode_c 类(在 r_modes.cc 中) .

当我尝试用 SDL2 替换所有内容时,我得到了从 SDL_Rect* 到 SDL_Rect** 的无效转换,所以也许我只是做错了。我花了几个月的时间试图让它工作,它就是不想。我不太关心设置每像素位数,因为现代机器现在可以默认为 24​​,而我们不再需要任何理由将其设置为 16 或 8(现在,每个人都有可以使用的 OpenGL 卡高于 16 位 BPP) ;)

任何建议、帮助...在这一点上的任何事情都将不胜感激 =)

谢谢! -卡萝兰

【问题讨论】:

使用SDL_GetDisplayMode() 的尝试在哪里给您带来演员错误? 我正在尝试通过历史记录找到该代码,但它现在似乎不存在(我想我是因为沮丧而将其删除..)。本质上,我调用了 SDL_GetDisplayMode() 而不是 SDL_ListModes,而不是 SDL_GetVideoInfo,我为此调用了 SDL2 函数。但我记得在尝试使其正常工作时遇到了某种 SDL_Rect 转换问题...:/ SDL2 非常适合在任何平台上拥有 GL 上下文,除了透明度,所以要更加努力...... 【参考方案1】:

使用 SDL_GetNumDisplayModes 和 SDL_GetDisplayMode 的组合,然后将它们推回到 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);
        
    

【讨论】:

以上是关于SDL1 -> 使用自定义屏幕模式类构建 SDL2 分辨率列表的主要内容,如果未能解决你的问题,请参考以下文章

如何为 android 的画中画模式创建自定义屏幕尺寸?

在没有类依赖的自定义类/子系统中使用 Laravel 4 模型

带有 @nguniversal 的 Angular s-s-r 和用于 PostCSS 支持的自定义 webpack

切换到 XCode 7.0(.1) 后,自定义视图 (XIB) 在发布模式下崩溃

使用 UITextView 的子类和自定义屏幕键盘,调用 textField.textShouldChange

如何自定义设置屏幕分辨率?