Posts Tagged ‘graphic’

[译文] XI2 食谱(1)

September 28th, 2009

作者:Peter Hutterer
原文发布时间:2009年6月26日
原文来源:http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html
译者:王旭 ( http://wangxu.me , @gnawux )
翻译时间:2009年9月28日

XI2 (X Input 2)目前已经进入 XServer 的主线了。在接下来的几天里,我将发布出来一组“食谱”,来介绍如何和这些新功能打交道。这里的例子仅仅是一些片段,每部分的完整的示例都将放在这里

09年7月13日更新:调整到新的 cookie event API

在第一部分中,我将介绍一些总体的信息,初始化以及事件选择。

为什么需要 XI2?

 

引入 XI2 的一个重要原因是要将 MPX 并入 X Server。当前的 1.5 版本的 X Input 扩展余地非常有限,很难进行扩展以完全支持 MPX。在 XI 1.5 上编程非常痛苦,所以,我们开始寻找一个替代方案,从而让支持多设备的程序更容易写一些,并且能灵活地应付将来的应用场景。

XI2 的协议时相当保守的,只增加了一些新的请求和事件,但它也留下了很多的发展空间。XI2 和它的 API 与 X 核心 API 的模式非常接近。从客户应用(X Client)的角度看,与 XI 的最大不同在于调用需要附带一个设备ID参数,不需要去打开设备,而事件类型和掩码都是常数(更多的在下面)。

现在,惟一的 XI2 绑定是 Xlib 绑定。尽管如此,我仍鼓励你开始采用 XI2 并思考程序如何使用它。通过现在进行测试,你可以在 2.0 发布之前帮助发现问题和当前版本中的缺陷。当然,在发布前修正 bug 可以惠及所有人。

MPX

 

MPX允许同时使用多个鼠标指针和键盘焦点。这将有助于引领相当时髦的用户界面——双手操作、多人操作……所有你能说出来的。它还抛弃了当前 GUI 设计的一些假设,但我将在将来再去谈这些。

MPX引入了一个显式的主/从设备层次关系。最简单的记住这个层次关系的方式是:物理设备是从设备,而鼠标指针或键盘焦点是主设备。

从设备附着到一个主设备上,每当从设备产生一个事件,这个事件将被通过主设备路由到客户应用上。主设备总是成对出现(一个指针,一个键盘焦点)。

这样,一个常见的配置可能是一个笔记本有四个主设备(两个键盘焦点和两个鼠标指针),触控板和内建键盘控制第一对主设备,一个USB无线键鼠套装控制第二对主设备。标准配置是有一堆主设备,所有设备都附着到这对主指针和焦点上。这个方案意外地(或无意外地)和我们自从 X Server 1.4 的配置是一样的。这也意味着除非你建立一对新的主设备,否则 MPX 根本就不可见。

我将在后面的文章里更多的介绍 MPX,从大多数客户应用的角度看,主设备是惟一需要关心的问题,只有配置工具和一些其他的特殊程序才真的需要去关心从设备。

XI2 初始化

 

一个典型的 XI2 程序如下面这么开头:

/* Connect to the X server */Display *dpy = XOpenDisplay(NULL);

/* XInput Extension available? */int opcode, event, error;if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error)) {   printf("X Input extension not available.\n");   return -1;}

/* Which version of XI2? We support 2.0 */int major = 2, minor = 0;if (XIQueryVersion(dpy, &major, &minor) == BadRequest) {  printf("XI2 not available. Server supports %d.%d\n", major, minor);  return -1;}

首先,客户应用连接 X Server,之后询问可用的 XI 扩展的版本。XQueryExtension 不仅告诉我们 XI 扩展是否存在,也会返回扩展的 opcode。这个 opcode 在事件处理时需要用到(所有的 XI2 事件都用到了这个 opcode)。这个 opcode 是在 X Server 启动时设置的,所以,在跨 X Server 的应用中,你不能把它当做个常量。

最后,我们宣布我们支持 XI 2.0,服务器返回它支持的版本。 XIQueryVersion 是一个纯 XI2 调用,即使你在一个不支持 XI2 的服务器上调用,它的实现也不会返回一个 BadRequest 错误(这是在 Xlib 中的实现,所以如果你使用xcb,这个行为可能会不同)。

XIQueryVersion 不仅返回支持的版本,X Server 也会存储你的客户应用支持的版本。随着 XI2 的进程,使用这个调用变得非常重要,服务器将根据支持的版本来区别对待不同的客户应用。

事件的选择


初始化GUI之后,客户应用通常需要选择事件。这一工作可以通过 XISelectEvents 实现。


XIEventMask eventmask;

unsigned char mask[1] = { 0 }; /* the actual mask */

eventmask.deviceid = 2;

eventmask.mask_len = sizeof(mask); /* always in bytes */

eventmask.mask = mask;

/* now set the mask */

XISetMask(mask, XI_ButtonPress);

XISetMask(mask, XI_Motion);

XISetMask(mask, XI_KeyPress);

/* select on the window */

XISelectEvents(display, window, &eventmask, 1);

XIEventMask 定义了一个设备的掩码。掩码定义为(1 事件类型),匹配位必须在 eventmask.mask 域中设置。eventmask.mask 的尺寸可以是任意大小的,倡导可以满足所有需要设置的掩码。XI_LASTEVENT 定义为当前 XI2 协议中的最高的事件类型,所以你可以使用它来确定需要设置的掩码的位数。在本例中,我们只需要6位,所以一个字节就够了。

XISelectEvents 携带了多个事件掩码,所以,你可以一次提交多个事件的选择(比如每个对应一个设备)。

如上所示,每个 XIEventMask 都带有一个设备ID。要么是一个设备的数字ID,或是 XIAllDevices 或 XIAllMasterDevices 这样的特殊 ID。如果你选择 XIAllDevices 的事件掩码,所有的设备都会送来选择的事件。XIAllMasterDevices 也是一样,但只是所有的主设备。

XIAllDevices 和 XIAllMasterDevices 的事件掩码是特定设备事件掩码的一个补充。例如,你可以选择所有设备的按下事件,所有主设备的松开事件,以及设备2的移动事件,设备2将会向客户应用报告所有三类事件(有效掩码是按位或的)。

并且,XIAllDevices 和 XIAllMasterDevices 对所有设备都会生效,即使设备在客户应用选择事件之后才加入也会生效。所以,你只要设置事件掩码一次,无需关心当前有多少设备可用,将来还会进入多少设备。

检查事件的非常简单:

XEvent event;XNextEvent(display, &event);if (ev.xcookie.type == GenericEvent &&    ev.xcookie.extension == opcode &&    XGetEventData(dpy, &ev.xcookie)){    switch(ev.xcookie.evtype)    {        case XI_ButtonPress:        case XI_Motion:        case XI_KeyPress:            do_something(ev.xcookie.data);            break;    }}XFreeEventData(dpy, &ev.xcookie);


对每个事件的数据进行更加细节的分析将在后面的文章中被介绍。

注意,你需要检查 XI 扩展的 opcode,和 XQueryExtension(3) 返回的 opcode 进行比较(如前所述)。

就这么简单,有了这些信息,你已经可以开始写简单的监听所有设备的事件的程序了。在下一部分,我将介绍如何列出输入设备,并监听主/从设备层次结构发生的变化。

[译文] GEM vs. TTM

August 8th, 2008

By Jonathan Corbet
May 28, 2008
王旭于2008年8月8日译
http://lwn.net/Articles/283793/

在 Linux 下,即使是在有了基础硬件的编程接口信息的情况系,得到高性能的 3D 渲染仍然是非常具有挑战性的。这个问题的一个原因就是内存管理:一个 GPU 本质上说是一个拥有它自己的独立的内存的计算机系统。要想管理GPU 的内存 —— 以及以它的视角看到的系统内存,让系统能够跑起来就必须要小心,更不要说还要获得可接受的性能了。

不久以前,这个问题看上去要被翻译表映射(TTM)子系统 解决了。TTM 目前仍然没有进入主线内核,依赖于它的所有驱动自然也没有进入。最近的一个关于 TTM 如何才能进入主线的提问引发了一场有趣的讨论,最终使得局面急转直下,TTM 可能根本就不是未来的显存管理系统。

很多关于 TTM 的抱怨都已经浮现出来了。它的 API 远大于任意一个开源 Linux 驱动的需求;换句话说,大量的代码都是用于二进制发布的驱动的。隔离机制(fence, 管理 CPU 和 GPU 的并发性的机制)非常复杂而难于使用,而且并不是总能得到很好的性能。大量的使用内存映射缓冲会给它自己带来性能问题。TTM API 尝试着提供所有情况下的一切东西;结果对于很多开发者来说很难让特定的硬件去匹配这些 API,很难开始使用 TTM,也缺乏足够的灵活性。对于使用TTM的开源驱动来说,这是一个重大的不足。所以 Dave Airlie 担忧地说 :

现在,我希望有一个 radeon 或是什么新的驱动已经使用了 TTM,或者,至少有个 demo 展示了如何使用它,可是现在什么也没有,这让我很痛苦……真正的问题是 TTM 是不是真的适合于 Linux 桌面和嵌入式驱动的开发者们,至少我在桌面方面还没看到足够的正面反馈。

所有这些但有看来都是徒劳的,毕竟 TTM 已经在那了,而且也没有什么其他的替代品。然而,事情发生了,一个转机发生了,它就叫做图形执行管理器(这名字翻译的好难听阿,对不起观众了),简称 GEM。Intel 资助的 GEM 项目已经有一个月了(译注:原文写于08年5月底,目前 GEM 形势大好阿)。GEM 的开发者其实还没完全准备好来对外公布他们的工作,不过 TTM 的讨论让他们提前走上了前台。

Keith Packard (译注:Intel 的开源图形驱动项目的带头人)的 GEM 介绍 中包含了一个已有 API 的描述文档。GEM 在处理上面有很多显著不同。首先 GEM 使用普通、匿名、用户空间内存来用于分配图形缓冲对象。这意味着这些缓冲区可以在必要的时候被交换出物理内存。这个方法有其显著的优越性,不仅仅是内存使用的灵活性:它让挂起和恢复的实现可以直接通过恢复所有缓冲对象的方式自动完成了。

GEM API 尽量避免将缓冲区到用户空间的映射。映射工作代价高昂而且而且带来了 CPU 与 GPU 之间的缓存一致性问题。所以,GEM 用简单的 read() 和 write() 调用来取代映射,访问缓冲区对象。或者,至少,在 GEM 开发者能给每个缓冲对象附加一个文件描述符的时候的处理方法。而内核不会那么轻易管理这么多文件描述符,这样,实际的 API 使用了不同的缓冲对象 handle 和一系列的 ioctl() 调用。

也就是说,GEM可能映射一个缓冲对象到用户空间。不过,用户空间的驱动必须显示地承担管理缓存一致性的责任。为此,有一组 ioctl() 调用用于管理缓冲的“域”;所谓“域”,本质上说就是描述了系统中的哪个组件拥有这块缓冲区并有权操作它。改变一个缓冲的域(两类域,其一用于读访问,而另一个是写)将会进行必要的缓存刷新。在某种意义上说,这个机制重现了流 DMA API,DMA API 中的 DMA 缓冲区的所有权就可以在 CPU 和 外设控制器之间交换。不必惊讶,他们解觉得也是类似的问题。

GEM API 不需要显示的屏蔽 (fence) 操作。相反,当 CPU 操作需要访问缓冲区的时候,如果必要的话 CPU 就会简单地等待 GPU 完成对该缓冲区的操作。

最后,GEM API 并没有想要独自解决所有问题;很多重要操作(比如执行一组 GPU 指令)被留给硬件特定的驱动来实现了。GEM 本身在目前非常适于 Intel 驱动的需求;它不需要达到所有的 TTM 所有达到的目标。Eric Anholt 描述 到:

TTM 的问题是它要对所有硬件提供一套统一的 API,即使我们的驱动不希望这样的时候也是如此……我们尽量从另一个方面来达到这一目的:实现一个驱动。当其他人实现了另一个驱动,又发现这里面有些代码应该是公共的,那么就将它移动到支撑库里并共享它。

这种方法的有点是更容易来给 Intel 新加入一些东西。而且这可能是个好的开始,一组工作的驱动总比没有强。另一方面,这也意味着要让 GEM 支持其它硬件的驱动还需要大量的工作。对于这些工作如何去做,目前大概有两种观点:(1) GEM 为新的驱动的需求增加新的能力,或者 (2) 让驱动使用它自己的内存管理器。

第一种方法在很多情况下看起来更漂亮。但它也预示着 GEM API 会经常发生很多变化。这可能会延缓整个系统进入主线内核的脚步;GEM API 会输出到用户空间,所以必须保持变化的兼容性。看起来必须要不断演进的 API 会在快速的进入主线内核的时候受到阻力。

而对于第二种方法,Dave Airlie 给出了最好的解释 :

嗯,事情是我不能相信我们还不足够知道如何以一种通用的方法来做到这点,不过 TTM vs GEM 可能已经证明了这是不可能的了。那么我们可以赌一赌每个驱动一个内存管理器,不过我怀疑这将成为一个维护的噩梦,所以如果人们决定了这就是下一步要走的,我会很高兴地看到他发生。不过提交第 n+1 个内存管理器的人必须解事情出接口后面的机制,而且解释清楚为什么不能复用内存管理器 1 到 n。

一个还没被讨论过的问题就是性能。Keith Whitwell 给出了一组评分结果 ,该结果显示对于 i915 驱动,使用 TTM 或 GEM 的时候,性能会比不使用的情况显著降低。而 Keith Packard 的到了不同的结果 ,他的结果显示 GEM 驱动的性能明显更好。显然,目前需要一组一致的 benchmark;图形性能是重要的,但如果不能有效地测量也就没法优化。

使用匿名内存也会引起一些性能考虑:如果第一人称射击游戏 (FPS) 的血腥像素们要不停地被换页的话,体验可能就不尽如人意了。匿名内存可以位于高位内存,而且这样就不必使用32位指针来访问。一些 GPU 硬件不能访问高位内存;这将可能影响 kernel 的 bounce buffer (不好意思啊,这个不知道怎么翻译好了)。最后,GEM 还需要去证明它可以提供良好的性能,GEM的开发者们非常主动地使他们的硬件看起来很好,这也让工作在上面的东西有了一个更好的机会。(这句话翻译的比较晕)

所有这些能得到的结论是GPU的内存管理问题还不能简单认为是已经解决了。GEM可能最终称为这个答案,但它还是非常新的API,仍然需要大量的工作。这个领域中似乎还有很多的工作需要做。

(感谢 Timo Jyrinki 建议这个话题。)

[译文] 技术预览:基于内核的显示模式设定

April 22nd, 2008

原文链接:http://www.phoronix.com/scan.php?page=article&item=kernel_modesetting
原文发表时间:2008年4月19日
原作者:
Michael Larabel
翻译时间:2008年4月22日
译者:王旭 gnawux(at)gmail.com

译者按:2008年9月19日,证实了一下,由于 TTM 到 GEM 的变化,kernel modesetting 没有进入到 2.6.27 之中,并且,刚刚尝试了一下,发现这个还很不成熟,不知道什么时候才能真的实用起来,可能需要 X driver 和 kernel, drm 等同时步进到一个稳定状态才行,这样看来,可能要到明年了。

X.Org 社区之中,不少新颖的技术都在萌芽之中——其中有Gallium3D (译注:新一代Linux 3D图形驱动框架), TTM 显存管理器(译注:用于GPU的显存管理),MPX (允许 X 拥有多个鼠标指针和键盘焦点)。不过,这些特色之中那个已经向着列表顶端进发、并给最终用户带来可以看到的好处的正是基于内核的显示模式设置(mode- setting)。正如其名字所表述的,基于内核的模式设置将显卡的模式设置代码从用户控件的X服务器驱动挪到了Linux内核。这个话题对最终用户似乎没什么意义,不过,将模式设置代码移动到内核将展现一个更简洁更漂亮的启动过程,增强挂起和恢复的支持,并提供更可靠的虚拟终端切换(等等)。内核的模式设置还没有进入主线内核,它的API也还没有冻结,不过,下个月将要发布的 Fedora 9 就将成为首个带有这一支持的主流发布版。本文中,我们将近距离观察配合 Intel X.Org 驱动的内核的模式设置及其工作时的视频(译注:译文将略过视频,请见谅)。

Radeon 驱动的移植工作 仍在进行中(驱动命名为 radeon_ms),不过 Fedora 9 将只包含带有这项支持的 Intel 开源 X.Org 驱动。内核的模式支持交互不是主线内核的内容,不过 Fedora 9 Intel 启动基于 intel-kernelmode 分支。intel-kernelmode 分支目前正在转向基于 intel-batchbuffer 分支。而 Intel-batchbuffer 也正是包含初始 DRI2 支持,TTM 现存管理,Render 改进,以及其他新鲜的改进的分支。在 Mesa/DRM 这边有一个 modesetting-101 分支。

因为内核不再依赖于外部资源来恢复显卡了,挂起和恢复的支持将有很大提高。因为这个过程如今在内核之中了,它能自动并且更快速恢复显示模式。类似地,虚拟终端的切换也因此被提高了。内核模式设置还将提升 debug 表现,这将可以消除所谓的“硬挂(hard hang)”,并将使显示图形化的错误信息成为可能(想象一下在 Linux 中来一个蓝屏死机)。有了这项技术,启动时只需要设置一次显示模式,而无需在开始启动过程的时候(对于Fedora来说,就是RH图形化启动)启动或关闭,然后再在X Server启动、显示GDM时再次初始化设备。基于内核的模式设置是 Intel 的 Keith Packard 列出的让人满意的 Linux 桌面的应有功能的项目列表之一。

基于内核的模式设置组间被缺省包含在 Fedora 9 之中了,但 Intel 的内核模式设置并不会缺省启动。要打开这个设置,需要在启动时在 grub 内参数列表里添上 i915.modeset=1,或是修改 /boot/grub/grub.conf (译注:对其他发布版可能应该是 menu.lst,另外,怀疑这个参数可以通过 modprobe.d 和 initramfs 设置,未经试验,纯属译者猜测)。除非有一天内核的显示模式设置被缺省使用了,这行命令才能省掉,否则总需要这条命令来让系统使用内核态模式设置而不是用户空间的 X 驱动。

Fedora 9 是惟一的一个今年春天发布的带有内核态模式设置功能的发布版。2.6.26 内核的 merge window 马上就要打开了,不过大家的一致看法是这一功能恐怕无法在 2.6.26 进入主线内核。这样,它进入主线内核的时间表将是这个秋天的 2.6.27,不过这恐怕对 Ubuntu 8.10 "Intrepid Ibex" 来说太迟了。Fedora 9 里面包含的只是个功能演示版。Red Hat 和 David Airlie 计划在 Fedora 10 中用内核态的模式设置来支持快速用户切换。

Intel-kernelmode 驱动支持 Intel 915 IGP 及更新的 Intel 显示芯片。为了这篇文章,我们在华擎ConRoe1333-DVI/H 主板上测试了刚刚发布的 Fedora 9 预览版,板载 Intel 945G 整合显卡,带有 VGA 和 DVI 接口。当连接到数字显示器并打开内核态模式设置时,启动过程是白了。RH图形化启动程序无法正确初始化显卡,到了启动GDM的时候,屏幕将闪动数次,但无法成功启动。而使用模拟显示器的时候,i915.modeset=1 可以顺利启动。不过,支持仍然不很完美。当使用内核态的模式设置驱动的时候,drmWaitVBlank 和 IRQ 仍有问题。

下面几页(译注:两页,四段 youtube 视频,略了)是内核态模式设置的工作视频。

基于内核的模式设置是 Linux 和 X.Org 将带给最终用户的显而易见的体验的巨大进步——干净而没有屏幕闪烁的启动过程、快速而稳定的虚拟终端切换、更好的挂起与恢复支持,而且很快将让“快速用户切换”更快。而这些仅仅是冰山一尖,更多的好处,比如图形化调试功能,也将会作为基于内核的显示模式设置功能的引入而显现出来。不过,现在还不是庆祝的时间。Redhat 和所有参与到为 Fedora 9 添加这一功能的出示支持的开发者都应得到赞赏,但仍然需要一段时间才能让更多图形驱动转移到内核态模式设置和并让其他发布版也支持这个功能。将模式设置代码转移到内核中并不是一个快速而直接的过程,但到今年年底,有希望达到一个比较好的状态。Intel 向 X.Org 提交的内容让他们成为了这个恐怖功能的第一个可以工作的驱动。由于内核态模式设置终将被采用并进入主线内核,我们将继续向大家展现更多亮点。

如果你尝试了 Intel 内核态模式设置,别忘了来 Phoronix 论坛 分享你的成果。

Switch to our mobile site