X11 设置
Linux 最好的特性之一是 XFree86,这是一个基于 X11R6 构建的免费窗口系统。当前版本 3.1.1 几乎可以在任何硬件上运行,因此您几乎没有理由不运行它。
您正在运行 XFree86 吗?这是一个不同的问题。如果您的答案是否定的,那么这篇文章可能适合您。
Linux 的另一个优点是它可以在 PC 上运行,PC 可以说是所有计算机系列中性价比最高的。(是的,我知道,人们一直在争论这一点。)
不幸的是,几乎没有两台 PC 具有相同的硬件配置;在 PC 的发展过程中,出现了数百种不同的显示卡,每种都有其独特的怪癖。它们是如何销售的?大多数人使用 DOS 或从 DOS 派生的系统,并且这些卡在板载了 DOS 所需的驱动程序软件。如果您正在运行真正的操作系统,您不想使用这些驱动程序:它们以 16 位模式运行,而且速度很慢。这就是 XFree86 提供自己的驱动程序并将其合并到 X 服务器中的原因。
XFree86 驱动程序的情况是“有好消息,也有坏消息”。先说坏消息:设置可能更困难。使用 Microsoft Windows,您安装板卡和随附的软件,它就可以工作(好吧,您可以在屏幕上获得可识别的图像)。使用 XFree86,事情可能没有那么容易。
好消息是驱动程序速度更快,也更灵活。特别是,如果您知道如何操作,即使您需要手动调整,您也可以将 XFree86 配置为与您的显示卡和显示器的确切组合相匹配。
这听起来可能很简单,也可能很复杂——而且确实如此。有些人只需几分钟即可设置好 X,但另一些人则会遇到让人崩溃的问题。在本文中,我们将探讨:
显示卡和显示器的工作原理。
如何设置 XFree86 以使其与您的硬件协同工作。
如何调整您的硬件以获得最大的显示性能。
如何烧毁您的显示器。
我最后一点是认真的。传统观点认为,编程错误不会损坏硬件,但在这种情况下,您可能会损坏硬件,而且人们有时会这样做。当您阅读完关于显示器如何工作的章节后,您就会明白,但请在了解所涉及的危险之前不要开始调整。
您不必成为计算机专家也能看出显示器和电视之间的相似之处;当前的显示器技术源于电视技术,许多显示卡都具有可以使用电视而不是显示器的模式。我们这些在 15 到 20 年前的微型计算机领域的人会记得在便携式电视上获得计算机显示的喜悦,一个以 300 或 1200 bps 运行的“玻璃 tty”。
电视和显示器通过扫描屏幕上的线来显示图像。就像在书中一样,第一行从屏幕的左上角开始,到右上角结束。每个连续的线都从略低于前一行的位置开始。这种情况一直持续到屏幕充满为止。这些线不必是完整的;图像是通过改变电子束在扫描线时的强度来形成的。
为了执行这种扫描,电视有两个 偏转单元:一个从左到右扫描,另一个(速度慢得多)从上到下扫描。不出所料,这些单元被称为 水平 和 垂直 偏转单元。您可能还会遇到术语 行 和 帧 偏转。
电子束只能以有限的速度移动。当电子束到达屏幕的右侧时,需要将其偏转回去。扫描的这一部分称为 水平回扫,它不用于显示图像数据。硬件执行回扫所需的实际时间各不相同,但大约占总行扫描时间的 5% 到 10%。同样,当垂直偏转到达屏幕底部时,它会执行 垂直回扫,这也不用于显示。
当然,仅仅偏转是不够的;您需要以某种方式确保扫描与传入信号同步,以便在屏幕顶部的信息到达时,扫描位于屏幕顶部。您都见过当这种情况没有发生时会发生什么;图像在屏幕上上下滚动(垂直同步不正确)或从屏幕左侧撕裂(水平同步不正确)。同步是通过在水平和垂直回扫周期中包含同步脉冲来实现的。为了确保它们被识别为同步脉冲,它们的电压电平与图像数据不同。
似乎这还不够,视频放大器(电视中改变光点在屏幕上移动时的强度的部分)需要时间来确保回扫是不可见的,因此在线的末尾和同步脉冲的开始之间,以及同步脉冲的末尾和数据的开始之间存在短暂的停顿。此过程称为 消隐,延迟称为 前沿(在同步脉冲之前)和 后沿(在同步脉冲之后)。
简而言之,这就是水平偏转的工作原理。垂直偏转的工作原理几乎相同,只是速度较慢,只有一个小例外。这种基本的显示机制是在 20 世纪 30 年代为电视开发的,当时“高科技”这个词甚至还没有发明出来,即使在今天,我们仍然受限于他们当时决定的低数据速率。根据国家/地区的不同,电视每秒仅显示 25 或 30 帧(显示页面)。这会在显示屏上引起不愉快的闪烁。这种闪烁可以通过一种称为 隔行扫描 的技巧来避免。帧不是在一个垂直扫描中显示,而是奇数行和偶数行在两个交替的半帧中显示,这会将表观帧频提高到 50 或 60 Hz。
那么我们如何将此应用于计算机显示器呢?让我们看一下美国标准 NTSC 系统——国际 PAL 和 SECAM 系统几乎相同,除了行数和垂直频率的细微差别。NTSC 规定了 525 行,但这包括垂直消隐时间,实际上只有大约 480 行是可见的。普通电视的宽高比为 4:3,换句话说,屏幕的宽度比高度宽三分之一,因此如果我们想要正方形像素(高度和宽度相同,这使得图形软件更简单),我们需要每行多三分之一的像素。这意味着我们可以在 480 行上显示每行 640 个像素。(这些数字看起来眼熟吗?现在您知道原因了。)
此分辨率通常缩写为“640*480”。PAL 和 SECAM 的垂直频率较低,允许标称 625 行,其中大约显示 580 行。无论哪种方式,这些值都有两个巨大的缺点:首先,它们是隔行扫描显示器,其次,分辨率是现代图形显示器可接受的最低水平。较旧的 PC 显示硬件,例如 CGA 和某些 EGA 模式,能够生成这些信号频率,但 VGA 再也无法做到这一点。在某些方面,这很遗憾;我想在客厅的电视上显示 X 显示,但我的最后一个 EGA 适配器几年前就坏了。
这些标准的第一个问题是隔行扫描。它对电视来说效果还不错,但对于计算机显示器来说却很麻烦——仍然比真正的 50 Hz 或 60 Hz 显示器闪烁得更厉害。VGA 仍然可以在隔行扫描模式下运行,但除非您有受虐倾向,否则您甚至不应该考虑这样做。第二个问题是分辨率;如今,1024*768 是足够正常的分辨率,但我正在 1280*1024 的显示器上编写本文,许多现代板卡都显示 1600*1200。另一方面,即使是 60 Hz 的刷新率也几乎不够。阅读任何营销文献,您都会发现 72 Hz 是闪烁突然消失的点。要获得高分辨率、高刷新率的显示器,您需要一些非常高的内部频率——我们稍后会看到有多高。
现在我们知道显示器只是一个经过美化的电视。电视的设计目的是将相同的电路用于水平偏转以及 CRT 所需的高压的产生。这简化了硬件设计,但代价是损失了通用性。产生高压的回扫变压器是一个谐振电路的一部分,该谐振电路只能在一个频率下工作。让回扫变压器脱离其预期频率运行,其效率会大大降低,并且会消耗更多功率。这种额外的功率将以热量的形式耗散在回扫变压器和水平输出晶体管中。结果可能是回扫变压器、晶体管或两者都发生故障。
您不必自己配置 X 才能烧毁显示器。十年前,标准的显示卡是 CGA(彩色图形适配器)和 HDA(Hercules 显示适配器),它们具有不同的水平偏转频率,因此需要不同的显示器。如果您将 HDA(18.43 kHz 水平偏转频率)连接到 CGA 显示器(15.75 kHz,NTSC 水平偏转频率),您可能会在几分钟内看到冒烟的迹象。
在现代 PC 显示器中,水平偏转和高压产生电路已分离。多频显示器能够在一定范围的偏转频率下运行。在指定范围内的任何频率下运行都可以,但仍有可能通过在指定范围外运行来损坏显示器。请注意,仅仅因为显示器正确显示图像并不意味着它在规范范围内运行。我有一台相当老旧的 Eizo 9500(在美国称为 Nanao),它有三个频率:(正好)31.5 kHz、48 到 50 kHz 或 64 到 78 kHz。实际上,它可以在 48 到 78 kHz 之间的任何频率下显示,但如果在 57 kHz 下运行很长时间,我将面临巨额维修费用。这个故事的寓意是:永远不要让您的显示器超出规格运行。如果您的显示器出现问题,很可能是频率超出范围。关闭显示器。
当然,显示器不是唯一可以烧毁的东西。如果您足够努力,您还可以通过在超出规格的频率下运行某些显示卡上的芯片来烧毁它们。但是,在实践中,这种情况发生的频率远没有那么高。
电视和显示器之间的另一个区别是它们接收的信号类型。真正的电视当然包括接收器,因此您有天线连接,但现代电视也具有来自录像机输入的连接,这些输入通常是音频信号和视频信号。视频信号由五个重要部分组成:红色信号、绿色信号、蓝色信号以及水平和垂直同步脉冲。这种信号称为 复合视频。相比之下,大多数现代显示器将这些信号分离到单独的信号线上,而较旧的板卡(例如 EGA)甚至每种颜色使用多条线。不幸的是,关于这些信号应如何工作,并没有完全达成一致;同步脉冲的极性因一个板卡而异,有些板卡会作弊并在绿色信号线上提供同步脉冲。这主要是历史兴趣,但偶尔您会遇到一个真正的便宜货 20 英寸显示器,它只有 3 个信号连接,您可能无法使其工作——这可能是原因之一。
显示控制器,通常称为 CRT(阴极射线管)控制器,是显示卡的一部分,它创建了我们刚才谈到的信号。早期的显示控制器旨在产生与电视兼容的信号。它们必须产生带有同步脉冲、前后沿和中间图像数据的信号。现代显示控制器可以做更多的事情,但原理仍然相同。
显示控制器的第一部分创建了我们正在寻找的框架:水平和垂直同步脉冲、消隐和图像信息,这些信息表示为一系列点或 点。为了计数,我们需要一个脉冲源,它也决定了单个点的持续时间,因此通常称为 点时钟。出于历史原因,CRT 控制器从显示屏的左上角开始计数,而不是从垂直同步脉冲开始计数,垂直同步脉冲才是显示的真正开始。为了向水平偏转定义一条线,我们需要设置四个 CRTC 寄存器来告诉它:
水平显示结束 (HDE) 寄存器指定我们希望每行有多少个点。在 CRTC 计数完这么多像素后,它会停止向显示器输出图像数据。
水平回扫开始 (SHR) 寄存器指定在同步脉冲开始之前发生多少个点时钟脉冲。此寄存器的内容与 HDE 寄存器的内容之间的差异定义了前沿的长度。
水平回扫结束 (EHR) 寄存器定义同步脉冲的结束。同步脉冲的宽度是此寄存器的内容与 SHR 寄存器的内容之间的差异。
水平总计 (HT) 寄存器定义每行的点时钟总数。后沿的宽度是此寄存器的内容与 EHR 寄存器的内容之间的差异。
此外,水平消隐开始 (SHB) 和 水平消隐结束 (EHB) 寄存器定义了何时关闭和打开视频信号。服务器会自动设置这些寄存器,因此我们无需更详细地查看它们。
垂直偏转的控制方式类似。在这种情况下,寄存器是 垂直显示结束 (VDE)、垂直回扫开始 (SVR)、垂直回扫结束 (EVR)、垂直总计 (VT)、垂直消隐开始 (SVB) 和 垂直消隐结束 (EVB)。这些寄存器中的值以行为单位计数。
VGA 硬件是从较旧的 8 位基于字符的显示硬件发展而来的,后者以字符而不是点时钟来计算行数。因此,所有这些寄存器都是 8 位宽的。这对于字符显示来说是足够的,但在计算点数时却是一个问题。您可以在任何这些寄存器中设置的最大值为 255。VGA 的设计者求助于许多糟糕的变通方法来解决这个问题。水平寄存器以 8 个点时钟为一组进行计数,因此它们最多可以表示 2048 个点时钟。垂直寄存器溢出到溢出寄存器中。即便如此,标准 VGA 也无法计数超过 1024 行。超级 VGA 在处理此问题的方式上有所不同,但通常它们会添加额外的溢出位。为了让您了解 VGA 设计有多么糟糕,在标准 VGA 上,真正的垂直总计(显示屏上的总行数)定义为 VT 寄存器的值 +256(如果溢出寄存器的位 0 已设置),或 +512(如果溢出寄存器的位 5 已设置)。
设置 XFree86 的步骤之一是定义这些寄存器值。幸运的是,您不必担心在溢出寄存器中设置哪些位。模式行以点为单位计数,服务器负责将点计数转换为显示卡可以理解的内容。典型的模式行如下所示:
"640x480a" 28 640 680 728 776 480 480 482 494
需要这十个值。此外,您可以在行尾指定修饰符。这些值是:
分辨率行的标签。这必须用引号括起来,并用于从 XF86Config 文件的其他部分引用该行。它是唯一的可选字段——稍后我们将研究当它不存在时会发生什么。传统上,标签表示显示模式的分辨率,但它不必如此。在此示例中,分辨率确实是 640*480,但标签末尾的 a 暗示这是一个替代值。
时钟频率。这可以是标签,如模式行标签,但有时它确实必须与 MHz 中的时钟频率匹配。
水平显示结束,进入 HDE 寄存器。此值和之后的所有值均以点为单位指定。服务器会根据显示卡的要求对它们进行修改,并将它们放入相应的 CRTC 寄存器中。
水平回扫开始 (SHR) 值。
水平回扫结束 (EHR) 值。
水平总计 (HT) 值。
垂直显示结束 (VDE) 值。此值和以下三个值以行为单位指定。
垂直回扫开始 (SVR) 值。
垂直回扫结束 (EVR) 值。
垂直总计 (VT) 值。
正如我所指出的,并非每个模式行都需要标签。可以为相同的分辨率设置多个模式行,每个模式行具有不同的点时钟频率。在这种情况下,一组行中只有第一行需要标签。
这些都是非常枯燥的内容。为了更容易理解,让我们看看我们将如何设置一个典型的 VGA 显示器,分辨率为 640*480 像素。当然,您可以在任何 XFree86 版本中找到此设置的值,但这并不意味着它们是 您的系统 的最佳值。我们想要一个无闪烁的显示器,我们将其理解为至少 72 Hz 的垂直频率,当然我们不想要隔行扫描。我们的多扫描显示器可以处理 15 到 40 kHz 之间的任何水平频率,因此让我们朝着最高频率前进,看看会发生什么。
首先,我们需要创建我们的行。它们包含 640 个像素、两个沿和一个同步脉冲。我们真正确定的唯一值是像素数。沿和同步脉冲应该有多长?如果您有一个好的显示器,并且有好的文档,它应该会告诉您,但大多数显示器制造商似乎不相信好的文档。当他们记录这些值时,它们在显示器与显示器之间,甚至在模式与模式之间也存在显着差异。它们不像看起来那么关键。例如,以下是我从 NEC 5D 手册中获得的一些典型值——水平同步脉冲:1 到 4 µs,前沿 0.18 到 2.1 µs,后沿 1.25 到 3.56 µs。
正如我们将看到的,这些时序参数的证明在于显示效果。如果显示效果良好,则参数没问题。我不知道有任何方法可以通过纯粹修改这些参数来损坏显示器,但是还有其他充分的理由坚持此范围。作为经验法则,如果您将这三个值中的每一个都设置为 2 µs 开始,您就不会犯太大的错误。或者,您可以从 NTSC 标准值开始。该标准规定水平同步脉冲持续 4.2 到 5.1 µs,前沿必须至少为 1.27 µs。NTSC 没有定义后沿的长度——Winstead 定义了总行消隐,其持续时间为 8.06 到 10.3 µs。为了我们的目的,我们可以将后沿视为总消隐的长度减去前沿和同步脉冲的长度。如果您取范围中间的某个值,您将获得 1.4 µs 的前沿、4.5 µs 的同步脉冲和 9 µs 的总消隐,这意味着后沿为 9 - 1.4 - 4.5 = 3.1 µs。
对于我们的示例,让我们坚持每个值 2 µs。我们的水平频率为 40 kHz,或每行 25 µs。在减去 6 µs 的总消隐时间后,我们只剩下 19 µs 用于显示数据。为了在这段时间内获得 640 个像素,我们需要每 19/640 µs 或大约 30 ns 一个像素。这对应于 33.6 MHz 的频率。这是我们所需的点时钟。
下一个问题是:我们是否有这个频率的点时钟?也许有。这应该在您的显示卡文档中,但我敢打赌它没有。没关系,XFree86 服务器足够聪明,可以自行找出答案——我们将在下一篇文章中看到如何操作。目前,让我们假设您确实有一个 33 MHz 的点时钟。您现在需要计算四个寄存器值来定义水平线:
第一个值是水平显示结束,即一行上的像素数。这很容易——它是 640。
您可以通过将前沿期间经过的点时钟数添加到 HDE 的值来计算 SHR。回想一下,我们决定前沿为 2 µs。在这段时间内,33 MHz 时钟将计数 66 个周期。所以我们加 66,对吗?错了。请记住,VGA 寄存器以 8 像素的增量计数,因此我们需要将前沿的宽度四舍五入为 8 的倍数。在这种情况下,我们将其四舍五入为 64,因此我们将 SHR 设置为 640 + 64 = 704。
我们需要的下一个值是 EHR,它是 SHR 加上水平回扫的宽度,再次为 64 个点时钟,因此我们将其设置为 704 + 64 = 768。
最终的水平值是 HT。同样,我们将前沿(64 个点时钟)添加到 EHR,得到 768 + 64 = 832。
接下来,我们需要另外四个值来定义垂直扫描。同样,在我们需要的四个值中,我们只知道行数。我们为沿和垂直同步使用多少行?正如我们所见,NTSC 将大约 45 行用于这三个组合,但在实践中,现代显示器使用的行数要少得多。再次参考 Multisync 手册,我们得到的前沿介于 0.014 和 1.2 µs 之间,同步脉冲介于 0.06 和 0.113 µs 之间,后沿介于 0.54 和 1.88 µs 之间。但这有多少行呢?
为了弄清楚这一点,我们需要知道我们的 真实 水平频率。我们的目标是 40 kHz,但我们在沿途做了一些权衡。真实的水平频率是点时钟除以水平总计,在本例中为 33 MHz / 832,这给了我们 39.66 kHz——非常不错。在该频率下,一行持续略超过 25 µs,因此我们的前沿范围可以在 ½ 到 48 行之间,同步脉冲在 2 到 5 行之间,后沿在 10 到 75 行之间。这些时序有意义吗?不,它们没有——它们只是显示器可以接受的值。
在实践中,我们可以采用每种情况下的最低值。很难指定 ½ 的值,因此我们将采用单行前沿。我们将采用两行同步脉冲和 10 行后沿。这给了我们:
VDE 为 480。
SVR 为 481。
EVR 为 483。
VT 为 493。
现在我们可以计算我们的垂直频率,即水平频率除以垂直总计,或 39.66/493 kHz,即 80.4 Hz——非常不错。相比之下,如果您使用 XF86config 中的标准条目,您将获得 31.5 kHz 的水平频率和仅 60 Hz 的垂直频率。
如果您了解显示器和显示卡的 technical details,那么它真的就是这么简单。此方法不需要太多思考,并且可以创建有效的结果。这并不意味着它们是最佳值——我们将在下一篇文章中对此进行研究。
Greg Lehey 是 LEMIS-Lehey Micro-computer Systems 的合伙人。他居住在德国。