Miyoo Mini移植Freedink时SDL_BlitSurface渲染部分翻转问题咨询
Freedink移植Miyoo Mini渲染异常问题
问题现象
移植过程中观测到三类渲染异常:
- 启动闪屏初始显示正常
- 室内场景下状态栏渲染正常,角色模型出现垂直翻转
- 房屋场景整体渲染错乱
初步排查怀疑问题出在SDL_BlitSurface函数,原始闪屏拷贝逻辑运行时仅场景渲染异常,新增中转缓冲区做二次blit后,原本正常的启动闪屏也出现翻转问题。
原始实现代码:
{ /* Copy splash to the background buffer so that D-Mod can start an effect from it (e.g. Pilgrim Quest's burning splash screen effect) */ SDL_BlitSurface(splash, NULL, GFX_lpDDSTwo, NULL); SDL_FreeSurface(splash); } /* Copy splash screen (again) to the screen during loading time */ SDL_BlitSurface(GFX_lpDDSTwo, NULL, GFX_lpDDSBack, NULL); flip_it();
修改后的中转逻辑代码:
{ /* Copy splash to the background buffer so that D-Mod can start an effect from it (e.g. Pilgrim Quest's burning splash screen effect) */ SDL_BlitSurface(splash, NULL, GFX_lpDDSThird, NULL); //First copy to GFX_lpDDSThird SDL_BlitSurface(GFX_lpDDSThird, NULL, GFX_lpDDSTwo, NULL); //And only then to GFX_lpDDSTwo SDL_FreeSurface(splash); } /* Copy splash screen (again) to the screen during loading time */ SDL_BlitSurface(GFX_lpDDSTwo, NULL, GFX_lpDDSBack, NULL); flip_it();
问题结论
该异常是Miyoo Mini平台官方SDK自带SDL1.2移植层的已知问题,和Freedink本身的业务逻辑无关。
根本原因
Miyoo Mini的帧缓冲驱动强制要求surface行跨度(pitch)必须满足16字节对齐,官方移植的SDL1.2未正确处理该对齐规则:
- 单次blit且源、目标surface的pitch偏差较小时,行地址计算误差不明显,对应初始状态下闪屏显示正常的现象
- 渲染带colorkey、Alpha通道的精灵、场景surface时,SDL blit逻辑会走像素格式转换路径,行地址计算错误直接导致垂直翻转、行顺序错乱,对应角色翻转、场景错乱的现象
- 新增中转缓冲区后多了一次blit,行地址误差累积,直接触发翻转逻辑,对应修改后闪屏也异常的现象
部分早期固件的SDL库还存在带Alpha通道surface blit时强制垂直翻转的硬编码错误,会进一步加剧渲染异常。
可行修复方案
按落地成本和稳定性从高到低排列:
- 替换修复版SDL库:使用社区维护的、已修复pitch对齐和blit翻转bug的SDL1.2库替换SDK中自带的官方版本,无需修改Freedink业务代码即可解决所有场景的渲染异常,是首选方案。
- 手动对齐surface宽度:如果暂不替换SDL库,创建所有离屏surface(包括
GFX_lpDDSTwo、GFX_lpDDSThird、GFX_lpDDSBack)时,将宽度向上对齐到16像素(RGB565格式下每个像素占2字节,16像素对应32字节行跨度,满足16字节对齐要求),blit时仅拷贝实际游戏分辨率对应的区域,即可规避pitch不对齐触发的blit逻辑bug。 - 自定义像素拷贝逻辑:临时适配可在调用
SDL_BlitSurface前手动校验源、目标surface的pitch对齐情况,不符合要求时逐行手动拷贝像素数据,绕过SDL存在bug的blit转换路径。
注意:不要尝试在业务层通过增减拷贝次数、调整blit顺序这类方式规避问题,这类方案只能覆盖闪屏等少数固定场景,运行D-Mod等自定义内容时必然出现其他兼容问题。
内容的提问来源于stack exchange,提问作者Илья Ефимов
相关产品推荐
相关产品推荐

