首页 > 解决方案 > SDL2 CreateTextureFromSurface 减慢

问题描述

我在 SDL2 中做一个图形界面,但是如果我用标志创建渲染器,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC与标志相比SDL_RENDERER_SOFTWARE,我认为这是不可能的。

我不能使用SDL_RENDERER_SOFTWARE,因为我需要启用 VSYNC 以避免撕裂,并且我需要双缓冲。

实际上我意识到瓶颈在于功能SDL_CreateTextureFromSurface()

就像我的代码很大一样,我会尝试解释它而不是在这里忽略所有内容:

  1. 初始化 SDL 并创建一个SDL_Surface命名的 screen_surface,SDL_CreateRGBSurface其大小与我的窗口相同,在该窗口中,任何其他表面都被 blit。
  2. 我在该表面的中间画了一个大正方形,SDL_FillRect并在该正方形内绘制了一个机架,使用两次 SDL_FillRect 绘制两个正方形,一个比下一个大 2 个像素,并且像这样模拟一个空正方形(我知道我可以相同,SDL_RenderDrawRect但我认为对于机架的每个单元格,在表面而不是渲染中绘制更佳),直到我有 4096 个单元格;

  3. 现在使用 SDL_TTF 我在每个单元格中写入信息,TTF_RenderUTF8_Blended用于获取每个单元格的表面,并SDL_BlitSurface用于“融合”这个表面与 screen_surface

  4. 最后,我想穿过一个大正方形,照亮正在检查的单元格,我用它SDL_FillRect来画一个穿过机架的小正方形。

  5. 最后我SDL_CreateTextureFromSurface在 screen_texture 中使用 for 变换 screen_surfaceSDL_RenderCopySDL_RenderPresent

这五个步骤在主要的内部,而事件管理并遵循 SDL_API 中的建议,我执行SDL_RenderClear每个循环以再次重绘所有内容。

说了这么多我在开始时所说的,我意识到瓶颈是第 5 步,独立于其他步骤,因为如果我采取第 2 步和第 3 步,并且我在此之前执行它们,同时离开内部,而仅创建机架照明一个黑色的窗口(因为我没有画任何东西)我得到了同样的减速。只有当我设法在不使用纹理的情况下绘制东西时,速度才会显着增加。

有我的问题:

  1. 为什么会发生这种情况?理论上使用双缓冲不应该比使用软件渲染器更快吗?

  2. 有什么形式可以在 Software Renderer 中模拟 vsync 吗?

  3. 我可以在不构建纹理的情况下渲染表面吗?

PD:我在互联网上阅读了一堆帖子,我将回答一些典型问题:我重新利用 screen_surface,我无法重新利用 TTF 返回的表面,我在每个循环中创建和破坏纹理(因为我认为我可以不要重复使用它)。

我把我的代码放在这里

int main(int ac, char **av)
{
    t_data      data;

    init_data(&data) /* initialize SDL */
    ft_ini_font(data); /* Initialize TTF */
    ft_ini_interface(data); 
    main_loop(&data);
    ft_quit_graphics(data); /* Close SDL and TTF */
    free(data);
    return (0);
}

void                main_loop(t_data *data)
{
    while (data->running)
    {
        events(data);
        SDL_BlitSurface(data->rack_surface, NULL, data->screen_surface, &(SDL_Rect){data->rack_x, data->rack_y, data->rack_w, data->rack_h}); /* Insert the rack in the screen_surface */
        ft_write_info(data);
        ft_illum_celd(data);
        set_back_to_front(data);
    }
}

void                ft_ini_interface(t_data *data)
{
    data->screen_surface = SDL_CreateRGBSurface(0, data->w, data->h, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK)
    ...
    /* stuff for calculate rack dims */
    ...
    data->rack_surface = generate_rack_surface(data);

}

void        generate_rack_surface(t_data *data)
{
    int i;
    int j;
    int k;

    data->rack_surface = SDL_CreateRGBSurface(0, data->rack_w, data->rack_h, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
    SDL_FillRect(Graph->rack, NULL, 0x3D3D33FF);
    ...
    /* ini i, j, k for drawn the rack properly */
    ...
    while (all cells not drawn)
    {
        if (k && !i)
        {
            data->celd_y += Graph->data->celd_h - 1;
            data->celd_x = 0;
            k--;
        }
        SDL_FillRect(data->rack, &(SDL_Rect){data->celd_x - 1, data->celd_y - 1, data->celd_w + 2, data->celd_h + 2}, 0x1C1C15FF))
        SDL_FillRect(data->rack, &(SDL_Rect){data->celd_x, data->celd_y, data->celd_w, data->celd_h}, 0x3D3D33FF)
        data->celd_x += data->celd_w - 1;
        i--;
    }
}

 void       ft_write_info(t_data *data)
{  
    SDL_Color color;
    char *info;

    while (all info not written)
    {
        color = take_color(); /*take the color of the info (only 4 ifs) */
        info = take_info(data); /*take info from a source using malloc*/
        surf_byte = TTF_RenderUTF8_Blended(data->font, info, color);
        ...
        /*stuf for take the correct possition in the rack */
        ...
        SDL_BlitSurface(surf_byte, NULL, Graph->screen.screen, &(SDL_Rect){data->info_x, data->info_y, data->celd.w, data->celd.h});
        SDL_FreeSurface(surf_byte);
        free(info);
    }

        void    ft_illum_celd(t_data *data)
{
    int color;
    SDL_Rect    illum;

    illum = next_illum(data) /* return a SDL_Rect with the position of the info being read */
    SDL_FillRect(data->screen_surface, &pc, color);
}

    void            set_back_to_front(t_data *data)
{
    SDL_Texture *texture;

    texture = SDL_CreateTextureFromSurface(data->Renderer, data->screen_surface);
    SDL_RenderCopy(data->Renderer, texture, NULL, NULL);
    SDL_DestroyTexture(texture);
    SDL_RenderPresent(data->Renderer);
    SDL_RenderClear(data->Renderer);
}

标签: csdl-2

解决方案


推荐阅读