我在SDL2中做图形界面,但是如果我创建带有标志SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
的渲染器,与标志SDL_RENDERER_SOFTWARE
相比我会明显变慢。我认为这是不可能的。
我不能使用SDL_RENDERER_SOFTWARE
,因为我需要启用VSYNC以避免撕裂,并且为此需要双重缓冲。
实际上,我意识到瓶颈在于功能SDL_CreateTextureFromSurface()
。
就像我的代码很大一样,我将尝试解释它,而不是在这里过去:
SDL_Surface
创建一个名为screen_surface的SDL_CreateRGBSurface
,其大小与我的窗口相同,否则将其他表面弄污。我用SDL_FillRect
在该表面的中间绘制一个大正方形,并使用两次SDL_FillRect在该正方形内部绘制一个机架,以绘制两个正方形,比下一个大2个像素,就像为机架中的每个单元格模拟一个空正方形(我知道我可以用SDL_RenderDrawRect
做同样的事情,但我认为在表面而不是“渲染”中是最佳的绘制方式),直到我有4096个单元格为止;
现在我使用SDL_TTF在每个单元格中写入信息,为此我使用TTF_RenderUTF8_Blended
获取每个单元格的表面,并使用SDL_BlitSurface
将该屏幕与screen_surface“融合”
最后,我想通过一个大方块来照亮被检查的单元格,我使用SDL_FillRect
绘制了一个穿过机架的小方块。
最后,我使用SDL_CreateTextureFromSurface
来变换screen_texture中的screen_surface,接着使用SDL_RenderCopy
和SDL_RenderPresent
这五个步骤是事件管理的主要步骤,并且遵循SDL_API中的建议,我每个循环SDL_RenderClear
再次绘制所有内容。
我一开始就这么说,我意识到瓶颈是与其他步骤无关的第5步,因为如果我采取第2步和第3步,并且在此之前做完,而仅在内部创建,在一个黑色的窗口上的机架照明(因为我什么都没画)我得到同样的减速。只有当我设法在不使用纹理的情况下绘制东西时,速度才会显着提高。
我有问题:
为什么会发生这种情况?从概念上讲,使用双重缓冲应该不会比使用Software Renderer更快?
在Software Renderer中可以模拟任何形式的vsync吗?
是否可以在不构建纹理的情况下渲染表面?
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);
}