SDL2 CreateTextureFromSurface变慢

时间:2018-07-19 11:42:58

标签: c sdl-2

我在SDL2中做图形界面,但是如果我创建带有标志SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC的渲染器,与标志SDL_RENDERER_SOFTWARE相比我会明显变慢。我认为这是不可能的。

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

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

就像我的代码很大一样,我将尝试解释它,而不是在这里过去:

  1. 初始化SDL并使用SDL_Surface创建一个名为screen_surface的SDL_CreateRGBSurface,其大小与我的窗口相同,否则将其他表面弄污。
  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中的screen_surface,接着使用SDL_RenderCopySDL_RenderPresent

这五个步骤是事件管理的主要步骤,并且遵循SDL_API中的建议,我每个循环SDL_RenderClear再次绘制所有内容。

我一开始就这么说,我意识到瓶颈是与其他步骤无关的第5步,因为如果我采取第2步和第3步,并且在此之前做完,而仅在内部创建,在一个黑色的窗口上的机架照明(因为我什么都没画)我得到同样的减速。只有当我设法在不使用纹理的情况下绘制东西时,速度才会显着提高。

我有问题:

  1. 为什么会发生这种情况?从概念上讲,使用双重缓冲应该不会比使用Software Renderer更快?

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

0 个答案:

没有答案