今天去 hacking thursday 的活动, 听一位朋友介绍了一下关于电脑是如何处理图形显示的东西, 整体脉络清楚了一些, 趁着记忆没有消散, 这里稍微整理一下.
我们先从显示器说起. 显示器负责真正把图像呈现给我们, 一般现在我们的电脑显示器可以接收数字信号也可以接收模拟信号, 数字的一般用 DVI, 模拟的一般 VGA 的接口. 传给显示器的数据不神奇, 就是图像数据流, 每个点拆分成RGB红绿蓝3原色的数值表示. VGA还要带的是 horizontal sync, vertical sync, 这个是水平和垂直扫描率, 就是每秒钟横竖扫描多少条, 就是我们说的屏幕分辨率再乘上没秒钟屏幕的刷新率. 这个数据丢给显示器, 显示器里面也有CPU, 负责控制屏幕把这样的数据显示出来, 也可能对这个数据做一点微调什么的, 比如我们显示器一般都有的对颜色位置亮度饱和度的调整.
要传给显示器的数据量是非常巨大的(根据屏幕尺寸), 也需要不断地传数据给显示器. 具体负责这些操作的是显卡. 现代的显卡要做相当多的事情. 不止是不间断地发送视频, 还会有渲染(3d游戏场景的渲染主要工作是交给显卡来做的), 视频数据解码等工作. 与上层的接口一般是通过显卡来读取特定的内存区块(DMA等方式)来实现. 简单地说, 告诉显卡, 主内存里面一个区块存放了需要显示的数据, 然后显卡自己过来取数据, 上层应用定时往这个内存区块放数据.
显卡会有自己的一些做事情的方式, 对于上层应用来说, 这些都是实现细节, 不需要知道. 显卡厂商会把功能抽象成opengl的API, 然后上层应用就调用这样的API即可. 在linux里面, Xwindow做的事情就是提供一个server/client的接口, 具体接口还是opengl.
然后我们到了更上层的gnome/kde, 它们是提供关于窗口绘制的api, 再往上面就是应用程序了, 调用gui的库来设置控件, 交互什么的.
如果上层应用需要直接发送显示的东西怎么办? 比如视频. 这个时候调用opengl的api, 申请一块内存区, 把渲染好的特定数据结构的图像放到这个内存区, 然后用opengl通知下层显示即可. 上层应用的进程需要控制刷新率, 一秒30桢的话就要刷30次, 如果应用是一个播放器的话, 可能需要多个线程, 一个线程用来做用户交互, 一个线程用来刷屏幕, 一个线程用来处理数据编码. 显卡也可以做解码的工作, 播放器可以控制显卡来解码, 这样显卡直接解码后写到显卡的缓存区块里面去.
具体技术细节非常复杂, 但是对于我来说, 对整体的过程有一个概念即可. 知道了原理就行了.