视频
视频驱动的概念和开发方式介绍。
最后更新于
视频驱动负责实现 LCUI 应用程序与操作系统中的视窗系统的交互,这些交互包括向 LCUI 应用程序提供屏幕尺寸、将组件的信息和渲染结果同步到对应的窗口中,是 LCUI 的几个驱动模块中最为复杂的一个。
表面(Surface)是窗口的抽象,也是 LCUI 的组件与操作系统的窗口进行交互的中间层,它屏蔽了各个操作系统中的视窗操作接口的差异和实现细节,使得 LCUI 应用程序只需要专注于将图形内容渲染到表面上,剩下的工作则交给视频驱动,它会将表面的尺寸、位置、标题等信息以及图形内容同步到对应的窗口。
LCUI 将表面的数据结构交由视频驱动在内部定义,应用层代码仅靠 LCUI_Surface
类型的指针来引用表面,对表面的操作都是靠调用表面的函数来实现的。
有三种显示模式:
LCUI_DMODE_WINDOWED
:窗口化模式,将根组件绑定到表面上,组件的宽高与表面宽高相同。
LCUI_DMODE_FULLSCREEN
:全屏模式,将根组件绑定到表面上,表面宽高与屏幕宽高相同。
LCUI_DMODE_SEAMLESS
:无缝模式,为根组件的每个直系子组件绑定一个表面。
初始显示模式是窗口化模式,你可以使用 LCUIDisplay_SetMode()
函数更改显示模式。
视频驱动接口在 中的定义如下:
接下来让我们深入了解这个结构体中的成员。
视频驱动的名称,用于标识当前使用的是哪个视频驱动。
获取屏幕的宽度。
获取屏幕的高度。
创建表面。你可以在这里初始化帧缓存、初始化表面信息、调用系统提供的接口创建窗口。
销毁表面。你可以在这里释放帧缓存、释放表面信息、调用系统提供的接口关闭窗口。
关闭表面。你可以在这里做销毁窗口的准备工作。这个函数是参考 Windows 的窗口关闭流程而设计的,关闭窗口时会收到 WM_CLOSE
消息,DefWindowProc()
函数对这个消息的处理就是调用 DestroyWindow()
销毁窗口。
调整表面尺寸。你可以在这里重新分配帧缓存、调用系统提供的接口调整窗口尺寸。
移动表面位置。你可以在这里调用系统提供的接口调整窗口位置。
显示表面。你可以在这里调用系统提供的接口显示窗口。
隐藏表面。你可以在这里调用系统提供的接口隐藏窗口。
更新表面。现有的视频驱动由于考虑到在其它线程上操作表面的情况,所以被设计成需要调用 update 函数才会应用所有的表面操作。不过现在还没有这种情况,你可以忽略这个函数。
呈现表面的最新内容。你可以在这里将帧缓存中的内容同步到主窗口中。
表面是否已经准备就绪。如果你的表面在 create()
函数中因某些原因无法立刻完成初始化,那么可以用这个函数返回 FALSE
告知 LCUI 这个表面暂时不能用,需要等待一会,直到返回 TRUE
为止。
开始绘制。你可以在这里完成绘制前的准备工作,例如创建绘制缓存区来存储接下来绘制的内容,然后返回绘制上下文。
结束绘制。你可以在这里将已绘制的内容更新到帧缓存中。
设置表面的说明文字。你可以在这里将表面的说明文字更新到窗口标题上。
设置表面的渲染模式。现在的渲染模式有拉伸和直接填充这两种,不过自定义渲染模式的场景很少,你可以忽略这个函数。
获取表面的窗口句柄。在 Windows 的视频驱动中,这个函数被用于在事件循环驱动中处理 WM_CLOSE
消息时判断应该关闭哪个表面。在其它系统的视频驱动中并没有这种处理,getHandle()
的返回值为 NULL,它们对窗口关闭事件的响应是直接退出 LCUI。
获取表面宽度。
获取表面高度。
设置表面透明度。其它视频驱动没有实现该功能,你可以忽略这个函数。
绑定事件。LCUI 会在主窗口主动触发尺寸变化、重绘、更新尺寸限制时做一些操作,例如:在用户主动拖拽调整窗口大小时,LCUI 会将表面的尺寸同步到与之绑定的组件上。
综上所述,假设你想添加的是适用于 Mac OS 的驱动,那么需要如下步骤:
按照 LCUI_DisplayDriver
中的函数指针的原型来定义函数。
定义 LCUI_CreateDarwinDisplayDriver
函数,在这个函数创建一个 LCUI_DisplayDriver
类型的对象,然后给它的 name
和函数指针设置正确的值。
如需了解更多,可参考现有的 Windows 和 Linux 系统的驱动:
调整视频驱动接口成员的命名
getWidth
获取的是屏幕的宽度, getSurfaceWidth
获取的是表面的宽度,按照这种命名风格,容易让人以为与表面相关的函数指针的命名应该都带有 Surface,然而实际上并没有。我们应该考虑将 getWidth
改成 getScreenWidth
,将 getSurfaceWidth
改成 getWidth
,但这样改的话,LCUI_DisplayDriver
是不是应该重命名为 LCUI_SurfaceDriver
?毕竟这个接口的操作集大都是针对表面的,而不是屏幕。
检验全屏模式和无缝模式是否工作正常
这两个显示模式已经很久没有测试过了,需要添加测试用例来检验是否能够正常工作。
在 中添加针对该操作系统的预处理指令: