SDL2 中的像素绘图和部分屏幕更新

问题描述 投票:0回答:1

我在 MS-DOS 中有一个用于 2 位 (CGA) 图形的现有库,并且我想使用相同的 API 来支持在使用 SDL2 的现代系统上使用相同 2 位资源的图形。基本上我想要一种简单的方法将过去和未来的 MS-DOS 项目移植到 Linux/Windows/Mac,也许还可以在 Linux 下开发新的 MS-DOS 项目(因为在 MS-DOS 下调试很痛苦)。

我的库在屏幕外存储 2 位缓冲区,并在需要时进行部分屏幕更新。处理图形操作调用的过程基本上是:(1)绘制到2位缓冲区并将需要更新的屏幕坐标添加到列表中; (2) 当列表达到容量或请求显式更新时,将缓冲区的更改部分传输到屏幕。这在原始 MS-DOS 库中运行良好且高效。

我使用 SDL 的方法是保留这个 2 位缓冲区 [1],并将更新从中复制(逐像素,除非有人能提出更好的方法)到 SDL_Renderer,然后使用 SDL_RenderPresent 将其传输到屏幕。

我发现的问题是,“后缓冲区在每次出现后都应被视为无效;不要假设先前的内容将存在于帧之间”,如文档所述。这是正确的:每隔一帧,屏幕上就会缺少一些东西 [2]。文档建议使用 SDL_RenderClear(),但这不适合我的应用程序,因为我进行部分屏幕更新;除了最新的更新之外,屏幕上的所有内容都会消失。

因此,使用渲染器似乎是单独绘制像素的正确方法,但渲染器不喜欢我需要的部分屏幕更新。根据我的阅读,完成我想要的操作的唯一方法是每次屏幕需要更新(无论多小)时将整个 2 位缓冲区逐像素复制到渲染器。我预计这会减慢速度,令人无法接受。

那么实现我想要的目标的正确方法是什么?

--

[1] 对于那些想问为什么的人...因为所有绘图操作都会写入此缓冲区,使用处理离屏 2 位位图绘图操作的相同代码,并且会更容易如果我保持这些绘图操作相同,则可以从 DOS/CGA 移植到 SDL,并且当我将此缓冲区的内容传输到屏幕时只需担心 SDL。

[2] 奇怪的是,我通过在每个“帧”之间放置 1 秒的暂停来正确更新图形,这似乎允许 SDL 在每次呈现后保持渲染器更新,原因我不明白。但显然 1fps 是不合适的,即使对于我正在开发的回合制游戏也是如此。我尝试在其位置使用 SDL_PollEvent() 循环,但这不起作用。

c sdl-2
1个回答
0
投票

所以,几周后,我得到了最接近答案的东西。 SDL2不支持2位图形;为此我必须等待 SDL3。

如果我需要 2 位图形,正确的方法似乎是每次有更新时,将 all 320x200 像素从我的 2 位后台缓冲区传输到 SDL_Renderer,逐个像素,然后 SDL_RenderPresent 到我的窗口上。这很慢,但似乎有效。至少在不运行 valgrind 时,它以回合制游戏可接受的速度运行(我还没有尝试使用 gdb)。

我的库(和 CGA 硬件)确实支持 1 位图形,其分辨率是 2 位图形的两倍,即 640x200。因此,在 SDL3 正确发布之前,我可以使用一种解决方法:强制 1 位模式并使用 SDL2 支持的 1 位 SDL_Surface,将 1 位更新从我的 1 位后台缓冲区传输到 1 位 SDL_Surface 。这不允许我为 Linux/Windows 进行发布质量移植,但它允许我使用 Linux 提供的调试工具在 Linux 下进行开发。

© www.soinside.com 2019 - 2024. All rights reserved.