c - SDL2 CreateTextureFromSurface 减慢
问题描述
我在 SDL2 中做一个图形界面,但是如果我用标志创建渲染器,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
与标志相比SDL_RENDERER_SOFTWARE
,我认为这是不可能的。
我不能使用SDL_RENDERER_SOFTWARE
,因为我需要启用 VSYNC 以避免撕裂,并且我需要双缓冲。
实际上我意识到瓶颈在于功能SDL_CreateTextureFromSurface()
。
就像我的代码很大一样,我会尝试解释它而不是在这里忽略所有内容:
- 初始化 SDL 并创建一个
SDL_Surface
命名的 screen_surface,SDL_CreateRGBSurface
其大小与我的窗口相同,在该窗口中,任何其他表面都被 blit。 我在该表面的中间画了一个大正方形,
SDL_FillRect
并在该正方形内绘制了一个机架,使用两次 SDL_FillRect 绘制两个正方形,一个比下一个大 2 个像素,并且像这样模拟一个空正方形(我知道我可以相同,SDL_RenderDrawRect
但我认为对于机架的每个单元格,在表面而不是渲染中绘制更佳),直到我有 4096 个单元格;现在使用 SDL_TTF 我在每个单元格中写入信息,
TTF_RenderUTF8_Blended
用于获取每个单元格的表面,并SDL_BlitSurface
用于“融合”这个表面与 screen_surface最后,我想穿过一个大正方形,照亮正在检查的单元格,我用它
SDL_FillRect
来画一个穿过机架的小正方形。最后我
SDL_CreateTextureFromSurface
在 screen_texture 中使用 for 变换 screen_surfaceSDL_RenderCopy
和SDL_RenderPresent
这五个步骤在主要的内部,而事件管理并遵循 SDL_API 中的建议,我执行SDL_RenderClear
每个循环以再次重绘所有内容。
说了这么多我在开始时所说的,我意识到瓶颈是第 5 步,独立于其他步骤,因为如果我采取第 2 步和第 3 步,并且我在此之前执行它们,同时离开内部,而仅创建机架照明一个黑色的窗口(因为我没有画任何东西)我得到了同样的减速。只有当我设法在不使用纹理的情况下绘制东西时,速度才会显着增加。
有我的问题:
为什么会发生这种情况?理论上使用双缓冲不应该比使用软件渲染器更快吗?
有什么形式可以在 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);
}
解决方案
推荐阅读
- angular - 在角度材质选项卡中设置水平滚动
- android - 我如何从 Gradle 测试中排除 Android 项目子模块的测试
- c# - Autofac 循环组件依赖 - 通用存储库
- c++ - 释放按钮时如何仅发送一次变量的值?
- php - 如何通过 str_replace 将值拆分为 wpallimport 以使用类别
- java - Spring Boot:按 ManyToOne 排序
- android - react-native-android 中的闪屏错误
- symfony - 如何将 symfony 和 vue 项目克隆到本地机器?
- java - springboot过滤器执行两次
- function - 如何修复 Tensorflow 2.0 中的“OperatorNotAllowedInGraphError”错误