揭开Wayland的面纱(一):X Window的前生今世

2024-05-26 17:38

本文主要是介绍揭开Wayland的面纱(一):X Window的前生今世,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自 https://imtx.me/archives/1573.html     向原创致敬!

*****************************************************************

今天大家可能在"Wow! Ubuntu"或其他地方看到了这篇文章:Ubuntu 决定未来将启用 Wayland X-Server。

Wayland是什么呢?它是X Window?还是要取代X Window?它的优势在哪里?Linux桌面/移动会因此有什么变化?在本篇中,我将回顾历史,展望未来,通过简易的文字,来先回顾一下X Window,从而继续解答Wayland。

注:在下对X Window的理解仅限于表面,文章中会有不少技术、历史方面的错误,若有大侠指出,不胜感激!

古老的X Window和现代的桌面技术

X Window在1984年由MIT研发,它的设计哲学之一是:提供机制,而非策略。举个最简单的例子吧:X Window提供了生成窗口(Window)的方法,但它没规定窗口要怎么呈现(map)或摆放(place),这个策略是由外部程序---- 窗口管理器(Window Manager)所决定的。另外一个X Window的主要特点便是:Server/Client网络模型。不论是本地、远程的应用程序,都统一通过Server/Client模型来运作,比如:让远程的应用程序跑在本地上。

X Window在推出之后快速演化,在1987年时候,其核心协议已经是第11版本了,简称:x11。这个版本已经将"提供机制,而非策略"这个哲学贯彻地非常彻底,以致于核心协议基本稳定,不需要特别大的改动。于是乎,你看到了,现在是2010年,整整23年了,X Window依然是X11。

你可能会诧异,23年了,X Window的核心都没有特别大的变化,它能适应现代桌面的快速发展吗?这就要再次提到X Window的设计优势了,X Window在核心层之外提供一个扩展层,开发者可以开发相应扩展,来实现自己的扩展协议,比方说:

标准的Window都是矩形的,我如何用它来画一个圆形的窗口?X Window协议并未提供,但是通过"shape"这个扩展,X Window可以实现不规则的窗体。

所以啊,这23年,X Window除了继续完善核心协议、驱动以外,很大程度上,都是扩展使它保持"与时俱进",比如说:

  • 要多头显示支持,这个是由"Xinerama"扩展实现的;
  • 要有多媒体视频回放的支持,这个是由"X Video"扩展实现的;
  • OpenGL的3D支持,则是通过"GL"扩展来实现的;
  • Compiz那样的合成桌面特效是怎么弄的?没错,还需要一个新的扩展,它便是:"Composite";
  • 甚至Keyboard的支持,都是通过"X Keyboard Extension"(也就是"XKB")的!

X Window的核心,基本上就是在处理Server/Client、驱动之类的,而外部的那些支持,基本上全是通过"扩展"进行的。这没什么不好,X Window的结构设计精良,尽管是扩展,但它们没有任何效能上的问题。通过扩展方便地实现了一些对新技术、新事物的支持,而且方便维护,这再好不过了。

所以你看到了尽管23年过去了,基于X Window的GNOME、KDE,还能保持与同期Windows、Mac OS X竞争甚至某些方面更好,你就不得不佩服这些前辈在最初设计时定下的设计哲学是多么正确了。

虽然扩展的众多没有给X Window造成什么问题,也跟X Window的设计哲学相符,但是其Server/Client的网络构架,却一直倍受质疑,这便是:

X Window的效率问题

经常听到有人说,X Window的Server/Client结构严重影响效率,导致Linux桌面的效应速度一直不如Windows、Mac OS X。事实是不是这样呢?让我们还是透过原理来说话吧。

这张,便是当前X Window系统的架构图,稍微解释一下:

  • X Client:图形应用程序,如Firefox、Pidgin等;
  • X Server:你看不见的控制中心;
  • Compositor:合成桌面系统,如Compiz;
  • Kernel/KMS/evdev:这便是Linux Kernel,后面会提到KMS技术了,其中还有一项evdev,是管理输入设备的。

X Architecture

通过这些箭头,你已经可以明白一些X Window的工作机制了,不过还从一个应用场景来解释一下,想像一下,当你点击了Firefox(X Client)的"刷新"按钮,将会发生以下事情:

  1. 你用鼠标点击了Firefox的"刷新"按钮,这时内核收到了鼠标发来的事件,并将其通过evdev输入驱动发送至了X Server。这时内核实际上做了很多事情,包括将不同品牌的鼠标发出的不同信号转换成了标准的"evdev"输入信息。
  2. 这时X Server可以判断哪个Window该收到这个消息,并将某座标按下按钮的消息发往X Client----Firefox。但事实上X Server并不知道它得到的窗口信息是不是正确!为什么呢?因为当前的Linux桌面早已经不是10年前的那样了,现在是"Composite"即合成桌面的时代,合成桌面的一个特点便是:Compositor(如Compiz)管理窗口的一切,X Server只能知道屏幕的某个点收到了鼠标消息,却不知道这个点下面到底有没有窗口----谁知道Compiz是不是正在搞一个漂亮的、缓慢的动画,把窗口收缩起来了呢?
  3. 假设应用场景没这么复杂,Firefox顺利地收到了消息,这时Firefox要决定该如何做:按钮要有按下的效果。于是Firefox再发送请求给X Server,说:"麻烦画一下按钮按下的效果。"
  4. 当X Server收到消息后,它就准备开始做具体的绘图工作了:首先它告诉显卡驱动,要画怎么样一个效果,然后它也计算了被改变的那块区域,同时告诉Compiz那块区域需要重新合成一下。
  5. Compiz收到消息后,它将从缓冲里取得显卡渲染出的图形并重新合成至整个屏幕----当然,Compiz的"合成"动作,也属于"渲染(render)",也是需要请求X Server,我要画这块,然后X Server回复:你可以画了。
  6. 整个过程可能已经明了了,请求和渲染的动作,从X Client->X Server,再从X Server->Compositor,而且是双向的,确实是比较耗时的,但是,事实还不是如此。介于X Window已有的机制,尽管Compiz已经掌管了全部最终桌面呈现的效果,但X Server在收到Compiz的"渲染"请求时,还会做一些"本职工作",如:窗口的重叠判断、被覆盖窗口的剪载计算等等(不然它怎么知道鼠标按下的坐标下,是Firefox的窗口呢)----这些都是无意义的重复工作,而且Compiz不会理会这些,Compiz依然会在自己的全屏幕"画布"上,画着自己的动画效果……

从这个过程,基本可以得出结论:

  1. X Client <-> X Server <-> Compositor,这三者请求渲染的过程,不是很高效;
  2. X Server,Compositor,这两者做了很多不必要的重复工作和正文切换。

当然,这里我没有直接说明这种模式有没有给X Window造成效率问题,因为我们还少一个对照组。再看对照组之前,再来看看X Server的另一个趋势:

从"什么都做"到"做得越来越少"的X Window

X Window刚出现那会,主要提供一个在操作系统内核上的抽象层,来实现一个图形环境。所谓图形环境,最主要的便是:图形+文字。当时的X Window便提供"绘图"和"渲染文字"的机制。图形桌面上的图案和文字,都通过X Window合成并绘制出来。

一个典型的例子,如果你要用X来画点,就要在你的程序中通过"XDrawPoint"来进行,X Server收到消息后,便会画出相应的点。

现在,稍微接触过图形开发的人都知道了,在X Window下,一般都通过GTK+和Qt来进行了。更深一层的是,通过Cairo(Qt不是)来绘制图形。Cairo是什么?它是一个绘图+渲染引擎,著名的浏览器Firefox,便是使用Cairo来渲染网页和文字的。

Cairo是一个全能的、跨平台的矢量绘图库,它不是简单的包装一下各个平台的绘图库而已,尽管它最初是基于X Window开发出来的绘图库。现在Cairo支持各种不同的后端,来向其输出图形,比如X、Windows的GDI、Mac OS X的Quartz,还有各种文件格式:PNG、PDF,当然还有SVG。可以说,Cairo是一个很彻底的、全能的绘图库,现在无论绘制什么图形,都不会考虑到用XLib了。

在Cairo之上,还有文字排版库:Pango,同样很明显的,处理文字排版,都不会用XFont之类的东西了,而是直接用Pango画。当然Pango也是跨平台的。

尽管在Linux平台下,Cairo、Pango的发挥依然是基于X Window的,但X Window充其量仅仅是一个"backend"而已,并不是少它不行。同理,跨平台的GTK+、Qt也只是视X为其中所支持的后端之一,假如哪天X真的不在了,更换一个新后端,当前的GNOME、KDE也能完整的跑起来。

再提另外一个比较典型的关于"X曾经做的,但现已不做"的例子,便是"模式设置(mode- setting)",说通俗点,就是"分辨率的设置",但后面会说明不仅仅如此。

大家都知道,Linux只是一个内核,它只有控制台,通过Shell来进行交互,而控制台默认是80x24(单位:字符)的,要进入分辨率1024x768或更高的图形模式,就需要X进行一次"模式设置",设置正确的分辨率等等。

尽管后来Linux也支持了各种用户层(user- space)的模式设置,让终端也支持标准的分辨率,但是X的模式设置与此是不相干的,所以一两年前,在Linux的启动过程中,从终端进入图形界面时,屏幕会"闪"一下,这时便在进行"模式设置" ----这里就一定要用"模式设置"这个术语了,因为即使终端是1024的,进入X图形也是1024的,模式的变更还是要进行。

后来呢,嗯,2009年初期,KMS(内核模式设置)终于出现了!!!很少关心桌面图形的Linux内核,在当时引入了"内核级"的模式设置,也就是说,在内核载入完毕、显示驱动初始化后很短的时间内,即设置好标准的分辨率和色深,通过在X层做相应的更改,从此X的初始化就可以省去"模式设置"这一过程了!也就是从Fedora 10开始,Linux的启动非常平滑、漂亮,没有任何闪烁了。现在的Ubuntu 10.10也一样,KMS的应用已经相当成熟。

X从此又少了一样图形任务……"X泪奔~你们都不要我了。"

可以说,这20多年来,X从"什么都做"已经到了"做的越来越少"。绝大多数的开发者开发图形应用程序,已经可以完全无视X的存在了,X现在更像是一个中间人的角色。那么,X这个中间人会不会有一天,完全被其他事物所取代呢?

没错!它便是下篇要介绍的:Wayland!!!

这篇关于揭开Wayland的面纱(一):X Window的前生今世的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1005138

相关文章

js window.addEventListener 是什么?

window.addEventListener 是 JavaScript 中的一个方法,用于向指定对象(在这个情况下是 window 对象,代表浏览器窗口)添加事件监听器,以便在该对象上发生特定事件时执行相应的函数(称为事件处理函数或事件监听器)。 这个方法接受三个参数: 事件类型(type):一个字符串,表示要监听的事件类型。例如,"click" 表示鼠标点击事件,"load" 表示页面加

Qt中window frame的影响

window frame 在创建图形化界面的时候,会创建窗口主体,上面会多出一条,周围多次一圈细边,这就叫window frame窗口框架,这是操作系统自带的。 这个对geometry的一些属性有一定影响,主要体现在Qt坐标系体系: 窗口当中包含一个按钮,这个按钮的坐标系是以父元素为参考,那么这个参考是widget本体作为参考,还是window frame作为参考,这两种参考体系都存在

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init

最初的window

不知你是否也是一个常年在MFC下编程的程序员,有的时候是否忘记了在MFC之前是如何写画窗口的了呢,或者你从来都只是机械的在MFC下面写代码,已经麻木了。其实有一个很简单的方法,或许能够帮你更清楚的了解WINDOW是怎么产生的。 随便用什么版本的VS,在创建win32工程的时候,直接创建WINDOW类型的就OK了。然后,来研究下产生的源代码吧。 // Global Variables:H

VC环境下window网络程序:UDP Socket程序

最近在学Windows网络编程,正好在做UDPsocket的程序,贴上来: 服务器框架函数:              socket();    bind();    recfrom();  sendto();  closesocket(); 客户机框架函数:            socket();      recfrom();  sendto();  closesocket();

Window下编译OpenJDK17

本文详细介绍Window下如何编译OpenJDK17,包含源码路径,各工具下载地址,严格按照文章中的步骤来操作,你将获得一个由自己亲手编译出的jdk。  一、下载OpenJDK17源码 下载地址:GitHub - openjdk/jdk at jdk-17+35 说明: 1、kkgithub为github的国内镜像,能够提高下载速度  2、下载下来的源码存放路径:无中文、无空格

POJ 2823 Sliding Window(线段树入门)

题意: 8 31 3 -1 -3 5 3 6 7 一串数列,有一个窗口大小为3,从数列开始往后移动,输出最大和最小值。 -1 -3 -3 -3 3 33 3 5 5 6 7 窗口大小为3 思路: 维护一个线段树,代码很详细 解题心得: 因为关键值的输入量有1000000,也就是叶节点有1000000个,总节点按理说是2000000-1,但这题得开3000000才能过

【DL--01】深度学习 揭开DL的神秘面纱

什么是深度学习 深度学习=深度神经网络+机器学习 人工智能 > 机器学习 > 表示学习 > 深度学习 神经元模型 输入信号、加权求和、加偏置、激活函数、输出 全连接层 输入信号、输入层、隐层(多个神经元)、输出层(多个输出,每个对应一个分类)、目标函数(交叉熵) 待求的参数:连接矩阵W、偏置b 训练方法:随机梯度下降,BP算法(后向传播) Python中深度学习实现:Ke

【机器学习】从零开始理解深度学习——揭开神经网络的神秘面纱

1. 引言 随着技术的飞速发展,人工智能(AI)已从学术研究的实验室走向现实应用的舞台,成为推动现代社会变革的核心动力之一。而在这一进程中,深度学习(Deep Learning)因其在大规模数据处理和复杂问题求解中的卓越表现,迅速崛起为人工智能的最前沿技术。深度学习的核心是神经网络,它模仿了生物神经系统的工作原理,通过层层叠加的结构化模型,逐步从数据中学习到有用的特征,从而完成分类、识别、生

linux下查看您当前是 Xorg(X11) 还是 Wayland方法

linux下查看您当前是 Xorg(X11) 还是 Wayland方法 方法如下(都是终端执行): echo $XDG_SESSION_TYPE 如果输出为wayland,则当前在 Wayland 环境中。 如果输出为x11,则当前在 X11 环境中。 或者 systemctl status display-manager 或者 loginctl show-session $(lo