OpenGL 是使用 Xlib 来绘制 windows 和渲染东西,还是相反?
Does OpenGL use Xlib to draw windows and render things, or is it the other way around?
我想使用 OpenGL 或 Xlib 在 window 上渲染字体和线条,但我想要知道哪个是 "more fundamental".
使用 Xlib 接口,我可以用这样的东西渲染这些东西(我发现 here):
// gcc x_1.c -o x_1 -lX11 && ./x_1
#include <stdio.h>
#include <X11/Xlib.h>
// This program draws a red line and some text in a chosen font.
Display *display;
Window window;
XSetWindowAttributes attributes;
XGCValues gr_values;
XFontStruct *fontinfo;
GC gr_context;
Visual *visual;
int depth;
int screen;
XEvent event;
XColor color, dummy;
int main() {
display = XOpenDisplay(NULL);
screen = DefaultScreen(display);
visual = DefaultVisual(display,screen);
depth = DefaultDepth(display,screen);
attributes.background_pixel = XWhitePixel(display,screen);
window = XCreateWindow( display,XRootWindow(display,screen),
200, 200, 350, 200, 5, depth, InputOutput,
visual ,CWBackPixel, &attributes);
XSelectInput(display,window,ExposureMask | KeyPressMask) ;
fontinfo = XLoadQueryFont(display,"6x10");
XAllocNamedColor(display, DefaultColormap(display, screen),"red",
&color,&dummy);
gr_values.font = fontinfo->fid;
gr_values.foreground = color.pixel;
gr_context=XCreateGC(display,window,GCFont+GCForeground, &gr_values);
XFlush(display);
XMapWindow(display,window);
XFlush(display);
while(1){
XNextEvent(display,&event);
switch(event.type){
case Expose:
XDrawLine(display,window,gr_context,0,0, 100, 100);
XDrawString(display,window,gr_context,100,100,"hello",5);
break;
case KeyPress:
XCloseDisplay(display);
return 1;
}
}
return 0;
}
现在,我可以使用纯 OpenGL 代码完成完全相同的事情,这引发了一些问题。
OpenGL 是否使用 Xlib 来显示 windows 和渲染 fonts/geometric 图元?还是反过来?
如果我想要更多地"low-level" 控制渲染和显示,我应该使用哪个?
编辑:
我的目标应用程序是一个准系统文本编辑器,它将只呈现 位图字体 ,只有 255 种颜色,并且只进行软件渲染(即假设没有 GPU)。
我尝试了Cairo/Pango、SDL2、GTK和Qt,但与纯 Xlib 相比,它们速度慢且反应迟钝。
Xlib 绘图命令通过网络套接字发送过时 请求。原始绘图命令已过时,例如当前的工具包不使用特定于文本的 X 请求。看起来仍在使用(抗锯齿)XRender 扩展。 X 服务器可以使用它喜欢的任何方法来实现请求。参见:魅力,使用 opengl 实现的 XRender。
OpenGL 同样是一个API,而不是一个具体的实现。
- 它在不依赖 X11 的平台上实现,包括 Windows。 (在这种情况下,X11 可作为第三方软件使用)。
- 它也在 Wayland 上实现,Wayland 是 Linux 上 X11 的后继者,否则没有 XRender 的等价物。
- 当 opengl 硬件加速不可用时,opengl 可能会在软件中呈现。
这个问题没有答案,你可以很容易地构建两种情况,或者只有两者之一可用,或者两者都实现硬件加速而不使用另一个,等等.
OpenGL 提供了更广泛的 GPU 功能,例如着色器编程。从这个意义上讲,它允许对硬件进行更全面的控制。
旁白:opengl有文字绘图api??我很困惑。
也许这个问题的作者打算包含一个 linux
标签。
快速谷歌搜索,我找到的最新文章here. I expect there's better somewhere. There's also a Wikipedia page on GLX
警告:即将出现文字墙!
@sourcejedi 已经给出了答案,但其中有一些不准确的地方——这不会造成伤害,但可能会造成混淆。
首先,OpenGL 和 Xlib 是相互正交的。两者都不依赖于另一个,您可以独立使用它们。 GLX 对 Xlib 有 依赖性(这就是为什么如果你想使用 GLX 就不能完全放弃 Xlib 而转而使用 Xcb),但该依赖性的表面积很小足够了,这样您就可以在大部分情况下使用 Xcb,而在必须使用 GLX 的少数部分使用 Xlib-on-Xcb 包装器。现在我在这里去掉了一些缩写词,所以让我们先分类一下:
Xlib 和 Xcb 都是实现 X11 协议客户端的库。从技术上讲,你可以在没有它们的情况下与 X11 服务器通信,通过实现协议 "yourself"(事实上,正在努力从也用于生成 Xcb 代码的相同规范文件自动生成 Haskell 代码) . X11 通过套接字传输,因此如果您能以某种方式在绑定之间传输该套接字和某些内部状态,您甚至可以混合和匹配绑定,如果您小心行事的话。
OpenGL本身是一个纯粹的低级(低级是指它提供的图元:点、线和三角形)绘图工具,里面没有"windows"的概念。随着帧缓冲区对象的引入,原则上您可以创建无头 OpenGL 上下文并完全在自我管理的图像表面范围内操作。但通常(但肯定不总是)您希望您的绘图在显示器上立即可见。这就是 window 系统接口 (WSI) 发挥作用的地方。尽管 OpenGL 以及围绕它的整个支持结构都相当陈旧,所以没有对整个 WSI 业务投入太多的思考,这导致了相当,好吧......实际上,到目前为止,根本没有为此定义清晰的接口,这一切都是偶然发生的。通常的方法是 "here I've got some preexisting image surface curtsey of the display system, I can haz OpenGL on that please?" 这将我们带到了 OpenGL 的相当特殊的 window 系统 API。 X11 的 GLX 和 Win32 的 WGL;苹果是它自己的一整章……
GLX 有两点:首先它是 X11 扩展,即它使用 X11 传输为 X11 服务器中的一组新命令创建通道。这些命令是为版本 1.1 到 2.1 指定的 OpenGL 函数(GLX 尚未指定用于 3.x 以后)。在这方面,GLX 在 X11 服务器端放置了一个 OpenGL 实现,GLX 操作码用于对 OpenGL 上下文 运行 服务器端的远程过程调用。 第二个 GLX 客户端实现,位于 libGL.so
OpenGL API 访问库中。
除此之外,GLX 还实现了一些 "convenience" 功能,例如从 X11 服务器端字体创建 OpenGL 显示列表光栅 "fonts";仅适用于自从 X11 核心以来一直存在的旧的和破坏的位图字体。不抗锯齿并且在低像素密度显示器上看起来不是特别好(如果你有高像素密度输出设备你可以不用抗锯齿和高分辨率位图字体实际上看起来很棒,例子:激光打印机)。 WGL 跟随 GLX 的脚步,对 Windows 位图字体做了同样的事情。这是直接内置到 OpenGL 生态系统中的唯一 "kind-of" 字体渲染支持。但它对于 7 位可打印 ASCII 集之外的任何东西几乎没有用。而且它完全缺少可以正确格式化文本(左对齐、右对齐、居中对齐、两端对齐或其他)的布局引擎。它完全依赖于显示列表和 OpenGL 光栅操作,它们有像 "the whole thing won't even go to work if the starting position of the first character happens to lie outside the viewport" 这样的警告。所以甚至不用费心去尝试使用它。
使用 GLX,您可以使用现有的 X11 window 并发送设置此 window 的 X11 服务器命令以用于 OpenGL。此外,使用 GLX,您可以发送 X11 服务器命令,要求它创建 OpenGL 上下文。 OpenGL 上下文不依赖于特定的 X11 可绘制对象。您可以自由附加和分离它,只要您打算附加的可绘制对象与该上下文 兼容(即已针对特定的帧缓冲区格式进行配置,该上下文期望它的主要帧缓冲区)。然后,当您进行 OpenGL 调用时,GLX 将它们包装成操作码并通过套接字连接将它们发送到执行它们的 X11 服务器。
当然,所有这些 de-/serialization 都会产生一些非微不足道的执行成本, 因此很快就会出现一种称为 "direct context"[= 的特殊模式61=] 被引入,其中 GLX/X11-server 组合仅用于设置 OpenGL 上下文并使其在 X11 可绘制对象上处于当前状态,其余程序直接针对 OpenGL 实现工作,从而避免所有序列化甚至直接访问大容量数据对象(纹理、缓冲区对象等)所在的地址 space。这就是为什么在基于 X11 的环境中,您可以找到 相同直接连接上下文 的 OpenGL 实现实例实际上存在于两个进程中:X11 服务器和使用它的客户端。
正如我在上面提到的 Xlib、Xcb & co 只是 X11 协议的客户端实现。 X11 的服务器端提供一组基本的图形功能。 X11 核心具有一些有限的位图字体绘制功能,以及绘制点、线、弧、(圆角)矩形、圆和多边形的功能。绘图和填充使用实心笔或阴影图案进行;没有插值或梯度发生。根据您要绘制的图像类型,这是相当有限的。在 2000 年到 2010 年之间,每个人都想画出色彩缤纷的 UI 有很多渐变和花哨的边框等等(我个人从来不喜欢那些),但在过去的几年里 semi-/flat UI 设计已经成为一种趋势,那些你实际上可以用 X11 核心绘制得相当好的(没有抗锯齿文本)。最终人们希望能够在 X11 端绘制渐变,因此引入了 XRender 扩展,它为您提供了本质上与 OpenGL 的 GL_TRIANGLES 原语等效的 2D,没有着色器、纹理和照明;不过,您可以获得颜色插值、渐变和抗锯齿。作为旁路,Xft 库(重要的是,这是一个库,而不是 X11 服务器的东西)被创建为搭载在 XRender 上以将一堆客户端光栅化字体字形加载到服务器,以便您可以将其用于可绘制对象 "antialiased" 文本。这是关于 X11 服务器的绘图功能。 如何在 X11 服务器中实际实现这些绘图功能是未指定的,完全取决于实现,更重要的是取决于设备相关的 X 代码 (DDX),即 X 图形驱动程序!它可能是纯粹在软件中完成(通常是这种情况,目前通过基于 pixman 渲染库的服务器端组件),但在使用的 OpenGL 的服务器端部分也有 GPU 加速甚至 based实施(魅力)。
Which one should I use if I want more "low-level" control over the rendering and display?
这完全取决于您的目标应用程序。
如果你的目标是做一些没有做很多图形图形的事情(文本编辑器、聊天程序等等)并且你可以接受 X11,那么可能是通过 Xlib 或 Xcb 的 X11。最重要的是,X11 为您提供了一些假装是半途合理的文本绘制功能,至少以可预测的方式工作。
如果您的目标是进行图形-图形工作(图像处理、CAD、桌面出版以及 Web 浏览器),OpenGL 是正确的选择,但这意味着您 "on your own"超越点、线和三角形。
如今,GPU 的存在几乎是理所当然的。 10 年前,并没有那么多,所以当时开发的 UI 工具包和图形后端(我们仍在使用它们)将在 CPU 上纯粹在软件中完成大部分工作并将最终图像传输到显示设备。这在当时是合理的。如果最终目标是可重现的,高质量的图形它仍然是,因为 GPU 为性能削减了很多角落并且行为不相同(OpenGL 要求在相同上下文中相同操作链的渲染结果 1:1 匹配,但只改变了一位,他们所有的赌注都关闭了)。
现在您可以在现代 Linux(!) 系统(通常不是基于 X11!)上找到并且可以使用 "stand-alone" 的三个渲染库是 Cairo 、Anti-Grain-Geometry (AGG) 和 pixman。 Cairo 主要用于基于 GDK/GTK+ 的程序,X11 服务器中的 pixman(但您也可以在您的程序中使用它)。 AGG 是 none 工具包的主要图形工具包,但被许多程序和库使用(最著名的是绘图,如 matplotlib)。还不能忘记 Qt 中的 "raster" 图形引擎,但它只能在 QPainter 中的 Qt 中使用(如果你的程序使用 Qt,那么它是独立的,但没有 Qt 就不能使用)。
当谈到 AGG vs. Cairo 时,Cairo 的最大卖点是它具有纯 C 绑定。不幸的是,Cairo 不是一个非常快的渲染器(它在过去 10 年取得了巨大进步)。但它吃的是 AGG 的灰尘,后者速度更快,而且(具有讽刺意味的是)还产生了更好的质量;不幸的是,AGG 是一个 C++ 库,因此要有效地使用它,您必须使用 C++,这是一个缺点。另外AGG的主要开发者几年前不幸去世,导致开发停滞了一段时间,但又被社区捡起来了。
无论您最终使用哪种图像引擎(也不要忘记 Wayland!),您都希望与 harbuzz-ng、freebidi、fontconfig 和 freetype 进行文本对话。 Unicode 和 Opentype 在那些日子里发展得如此之快,你自己重新实现相应的引擎并不是很有趣。
您可能认为 7 位 ascii 就足够了,但现在即使是嵌入式设备也能做更多(如果只是渲染 i18n 流、音乐标签等)。
Pango-Cairo 曾经是整合所有这些的标准方式。但是现在许多大型应用程序都在转向 skia 以提高速度。
简答(使用 Xlib/XCB/GLX/OpenGL 推断)和 Youtube tutorial:
- Xlib is a high-level C wrapper around the X protocol(客户端)。
- XCB is a low-level C warpper around the X protocol(客户端)。
- X window System 作为“客户端-服务器”系统工作,其中“X 服务器”是 GPU,“X 客户端”是您的应用程序。
- X 客户端和 X 服务器使用 X Protocol 通过套接字相互发送 requests/replies/errors/events(每个 32 字节长?)。
- GLX is both a protocol extension and an API 将 X Window 系统连接到 OpenGL 并允许 X 资源(例如 X window 或 X 像素图)用于 OpenGL 调用。
- OpenGL是一个图形API,它向GPU发送draw/memory命令。它在通常称为
libGL.so
的共享库中实现,对于 NVIDIA,它是由 NVIDIA 实现的。
- OpenGL 应用程序需要 X display/connection、X 屏幕、X window(或 GLX window),X 颜色图,GLX fbconfig 和 GLX context,然后才能进行第一个 OpenGL 调用。然后在 X window(或 GLX window)上呈现 OpenGL 调用的结果。
- 那个Linux kernel has the DRI, the DRM, and the KMS,貌似比Xlib/XCB/GLX/OpenGL低级,完全不可见(接近GPU驱动的级别,其实我觉得NVIDIA驱动可能会绕过一个一大块内核基础设施?)。
因此,Xlib/XCB 创建 windows,然后 OpenGL 渲染它们。
(OpenGL 无法创建 windows。Xlib/XCB 可以 渲染,但我认为这与 GPU 加速无关。)
我想使用 OpenGL 或 Xlib 在 window 上渲染字体和线条,但我想要知道哪个是 "more fundamental".
使用 Xlib 接口,我可以用这样的东西渲染这些东西(我发现 here):
// gcc x_1.c -o x_1 -lX11 && ./x_1
#include <stdio.h>
#include <X11/Xlib.h>
// This program draws a red line and some text in a chosen font.
Display *display;
Window window;
XSetWindowAttributes attributes;
XGCValues gr_values;
XFontStruct *fontinfo;
GC gr_context;
Visual *visual;
int depth;
int screen;
XEvent event;
XColor color, dummy;
int main() {
display = XOpenDisplay(NULL);
screen = DefaultScreen(display);
visual = DefaultVisual(display,screen);
depth = DefaultDepth(display,screen);
attributes.background_pixel = XWhitePixel(display,screen);
window = XCreateWindow( display,XRootWindow(display,screen),
200, 200, 350, 200, 5, depth, InputOutput,
visual ,CWBackPixel, &attributes);
XSelectInput(display,window,ExposureMask | KeyPressMask) ;
fontinfo = XLoadQueryFont(display,"6x10");
XAllocNamedColor(display, DefaultColormap(display, screen),"red",
&color,&dummy);
gr_values.font = fontinfo->fid;
gr_values.foreground = color.pixel;
gr_context=XCreateGC(display,window,GCFont+GCForeground, &gr_values);
XFlush(display);
XMapWindow(display,window);
XFlush(display);
while(1){
XNextEvent(display,&event);
switch(event.type){
case Expose:
XDrawLine(display,window,gr_context,0,0, 100, 100);
XDrawString(display,window,gr_context,100,100,"hello",5);
break;
case KeyPress:
XCloseDisplay(display);
return 1;
}
}
return 0;
}
现在,我可以使用纯 OpenGL 代码完成完全相同的事情,这引发了一些问题。
OpenGL 是否使用 Xlib 来显示 windows 和渲染 fonts/geometric 图元?还是反过来?
如果我想要更多地"low-level" 控制渲染和显示,我应该使用哪个?
编辑:
我的目标应用程序是一个准系统文本编辑器,它将只呈现 位图字体 ,只有 255 种颜色,并且只进行软件渲染(即假设没有 GPU)。
我尝试了Cairo/Pango、SDL2、GTK和Qt,但与纯 Xlib 相比,它们速度慢且反应迟钝。
Xlib 绘图命令通过网络套接字发送过时 请求。原始绘图命令已过时,例如当前的工具包不使用特定于文本的 X 请求。看起来仍在使用(抗锯齿)XRender 扩展。 X 服务器可以使用它喜欢的任何方法来实现请求。参见:魅力,使用 opengl 实现的 XRender。
OpenGL 同样是一个API,而不是一个具体的实现。
- 它在不依赖 X11 的平台上实现,包括 Windows。 (在这种情况下,X11 可作为第三方软件使用)。
- 它也在 Wayland 上实现,Wayland 是 Linux 上 X11 的后继者,否则没有 XRender 的等价物。
- 当 opengl 硬件加速不可用时,opengl 可能会在软件中呈现。
这个问题没有答案,你可以很容易地构建两种情况,或者只有两者之一可用,或者两者都实现硬件加速而不使用另一个,等等.
OpenGL 提供了更广泛的 GPU 功能,例如着色器编程。从这个意义上讲,它允许对硬件进行更全面的控制。
旁白:opengl有文字绘图api??我很困惑。
也许这个问题的作者打算包含一个 linux
标签。
快速谷歌搜索,我找到的最新文章here. I expect there's better somewhere. There's also a Wikipedia page on GLX
警告:即将出现文字墙!
@sourcejedi 已经给出了答案,但其中有一些不准确的地方——这不会造成伤害,但可能会造成混淆。
首先,OpenGL 和 Xlib 是相互正交的。两者都不依赖于另一个,您可以独立使用它们。 GLX 对 Xlib 有 依赖性(这就是为什么如果你想使用 GLX 就不能完全放弃 Xlib 而转而使用 Xcb),但该依赖性的表面积很小足够了,这样您就可以在大部分情况下使用 Xcb,而在必须使用 GLX 的少数部分使用 Xlib-on-Xcb 包装器。现在我在这里去掉了一些缩写词,所以让我们先分类一下:
Xlib 和 Xcb 都是实现 X11 协议客户端的库。从技术上讲,你可以在没有它们的情况下与 X11 服务器通信,通过实现协议 "yourself"(事实上,正在努力从也用于生成 Xcb 代码的相同规范文件自动生成 Haskell 代码) . X11 通过套接字传输,因此如果您能以某种方式在绑定之间传输该套接字和某些内部状态,您甚至可以混合和匹配绑定,如果您小心行事的话。
OpenGL本身是一个纯粹的低级(低级是指它提供的图元:点、线和三角形)绘图工具,里面没有"windows"的概念。随着帧缓冲区对象的引入,原则上您可以创建无头 OpenGL 上下文并完全在自我管理的图像表面范围内操作。但通常(但肯定不总是)您希望您的绘图在显示器上立即可见。这就是 window 系统接口 (WSI) 发挥作用的地方。尽管 OpenGL 以及围绕它的整个支持结构都相当陈旧,所以没有对整个 WSI 业务投入太多的思考,这导致了相当,好吧......实际上,到目前为止,根本没有为此定义清晰的接口,这一切都是偶然发生的。通常的方法是 "here I've got some preexisting image surface curtsey of the display system, I can haz OpenGL on that please?" 这将我们带到了 OpenGL 的相当特殊的 window 系统 API。 X11 的 GLX 和 Win32 的 WGL;苹果是它自己的一整章……
GLX 有两点:首先它是 X11 扩展,即它使用 X11 传输为 X11 服务器中的一组新命令创建通道。这些命令是为版本 1.1 到 2.1 指定的 OpenGL 函数(GLX 尚未指定用于 3.x 以后)。在这方面,GLX 在 X11 服务器端放置了一个 OpenGL 实现,GLX 操作码用于对 OpenGL 上下文 运行 服务器端的远程过程调用。 第二个 GLX 客户端实现,位于 libGL.so
OpenGL API 访问库中。
除此之外,GLX 还实现了一些 "convenience" 功能,例如从 X11 服务器端字体创建 OpenGL 显示列表光栅 "fonts";仅适用于自从 X11 核心以来一直存在的旧的和破坏的位图字体。不抗锯齿并且在低像素密度显示器上看起来不是特别好(如果你有高像素密度输出设备你可以不用抗锯齿和高分辨率位图字体实际上看起来很棒,例子:激光打印机)。 WGL 跟随 GLX 的脚步,对 Windows 位图字体做了同样的事情。这是直接内置到 OpenGL 生态系统中的唯一 "kind-of" 字体渲染支持。但它对于 7 位可打印 ASCII 集之外的任何东西几乎没有用。而且它完全缺少可以正确格式化文本(左对齐、右对齐、居中对齐、两端对齐或其他)的布局引擎。它完全依赖于显示列表和 OpenGL 光栅操作,它们有像 "the whole thing won't even go to work if the starting position of the first character happens to lie outside the viewport" 这样的警告。所以甚至不用费心去尝试使用它。
使用 GLX,您可以使用现有的 X11 window 并发送设置此 window 的 X11 服务器命令以用于 OpenGL。此外,使用 GLX,您可以发送 X11 服务器命令,要求它创建 OpenGL 上下文。 OpenGL 上下文不依赖于特定的 X11 可绘制对象。您可以自由附加和分离它,只要您打算附加的可绘制对象与该上下文 兼容(即已针对特定的帧缓冲区格式进行配置,该上下文期望它的主要帧缓冲区)。然后,当您进行 OpenGL 调用时,GLX 将它们包装成操作码并通过套接字连接将它们发送到执行它们的 X11 服务器。
当然,所有这些 de-/serialization 都会产生一些非微不足道的执行成本, 因此很快就会出现一种称为 "direct context"[= 的特殊模式61=] 被引入,其中 GLX/X11-server 组合仅用于设置 OpenGL 上下文并使其在 X11 可绘制对象上处于当前状态,其余程序直接针对 OpenGL 实现工作,从而避免所有序列化甚至直接访问大容量数据对象(纹理、缓冲区对象等)所在的地址 space。这就是为什么在基于 X11 的环境中,您可以找到 相同直接连接上下文 的 OpenGL 实现实例实际上存在于两个进程中:X11 服务器和使用它的客户端。
正如我在上面提到的 Xlib、Xcb & co 只是 X11 协议的客户端实现。 X11 的服务器端提供一组基本的图形功能。 X11 核心具有一些有限的位图字体绘制功能,以及绘制点、线、弧、(圆角)矩形、圆和多边形的功能。绘图和填充使用实心笔或阴影图案进行;没有插值或梯度发生。根据您要绘制的图像类型,这是相当有限的。在 2000 年到 2010 年之间,每个人都想画出色彩缤纷的 UI 有很多渐变和花哨的边框等等(我个人从来不喜欢那些),但在过去的几年里 semi-/flat UI 设计已经成为一种趋势,那些你实际上可以用 X11 核心绘制得相当好的(没有抗锯齿文本)。最终人们希望能够在 X11 端绘制渐变,因此引入了 XRender 扩展,它为您提供了本质上与 OpenGL 的 GL_TRIANGLES 原语等效的 2D,没有着色器、纹理和照明;不过,您可以获得颜色插值、渐变和抗锯齿。作为旁路,Xft 库(重要的是,这是一个库,而不是 X11 服务器的东西)被创建为搭载在 XRender 上以将一堆客户端光栅化字体字形加载到服务器,以便您可以将其用于可绘制对象 "antialiased" 文本。这是关于 X11 服务器的绘图功能。 如何在 X11 服务器中实际实现这些绘图功能是未指定的,完全取决于实现,更重要的是取决于设备相关的 X 代码 (DDX),即 X 图形驱动程序!它可能是纯粹在软件中完成(通常是这种情况,目前通过基于 pixman 渲染库的服务器端组件),但在使用的 OpenGL 的服务器端部分也有 GPU 加速甚至 based实施(魅力)。
Which one should I use if I want more "low-level" control over the rendering and display?
这完全取决于您的目标应用程序。
如果你的目标是做一些没有做很多图形图形的事情(文本编辑器、聊天程序等等)并且你可以接受 X11,那么可能是通过 Xlib 或 Xcb 的 X11。最重要的是,X11 为您提供了一些假装是半途合理的文本绘制功能,至少以可预测的方式工作。
如果您的目标是进行图形-图形工作(图像处理、CAD、桌面出版以及 Web 浏览器),OpenGL 是正确的选择,但这意味着您 "on your own"超越点、线和三角形。
如今,GPU 的存在几乎是理所当然的。 10 年前,并没有那么多,所以当时开发的 UI 工具包和图形后端(我们仍在使用它们)将在 CPU 上纯粹在软件中完成大部分工作并将最终图像传输到显示设备。这在当时是合理的。如果最终目标是可重现的,高质量的图形它仍然是,因为 GPU 为性能削减了很多角落并且行为不相同(OpenGL 要求在相同上下文中相同操作链的渲染结果 1:1 匹配,但只改变了一位,他们所有的赌注都关闭了)。
现在您可以在现代 Linux(!) 系统(通常不是基于 X11!)上找到并且可以使用 "stand-alone" 的三个渲染库是 Cairo 、Anti-Grain-Geometry (AGG) 和 pixman。 Cairo 主要用于基于 GDK/GTK+ 的程序,X11 服务器中的 pixman(但您也可以在您的程序中使用它)。 AGG 是 none 工具包的主要图形工具包,但被许多程序和库使用(最著名的是绘图,如 matplotlib)。还不能忘记 Qt 中的 "raster" 图形引擎,但它只能在 QPainter 中的 Qt 中使用(如果你的程序使用 Qt,那么它是独立的,但没有 Qt 就不能使用)。
当谈到 AGG vs. Cairo 时,Cairo 的最大卖点是它具有纯 C 绑定。不幸的是,Cairo 不是一个非常快的渲染器(它在过去 10 年取得了巨大进步)。但它吃的是 AGG 的灰尘,后者速度更快,而且(具有讽刺意味的是)还产生了更好的质量;不幸的是,AGG 是一个 C++ 库,因此要有效地使用它,您必须使用 C++,这是一个缺点。另外AGG的主要开发者几年前不幸去世,导致开发停滞了一段时间,但又被社区捡起来了。
无论您最终使用哪种图像引擎(也不要忘记 Wayland!),您都希望与 harbuzz-ng、freebidi、fontconfig 和 freetype 进行文本对话。 Unicode 和 Opentype 在那些日子里发展得如此之快,你自己重新实现相应的引擎并不是很有趣。
您可能认为 7 位 ascii 就足够了,但现在即使是嵌入式设备也能做更多(如果只是渲染 i18n 流、音乐标签等)。
Pango-Cairo 曾经是整合所有这些的标准方式。但是现在许多大型应用程序都在转向 skia 以提高速度。
简答(使用 Xlib/XCB/GLX/OpenGL 推断)和 Youtube tutorial:
- Xlib is a high-level C wrapper around the X protocol(客户端)。
- XCB is a low-level C warpper around the X protocol(客户端)。
- X window System 作为“客户端-服务器”系统工作,其中“X 服务器”是 GPU,“X 客户端”是您的应用程序。
- X 客户端和 X 服务器使用 X Protocol 通过套接字相互发送 requests/replies/errors/events(每个 32 字节长?)。
- GLX is both a protocol extension and an API 将 X Window 系统连接到 OpenGL 并允许 X 资源(例如 X window 或 X 像素图)用于 OpenGL 调用。
- OpenGL是一个图形API,它向GPU发送draw/memory命令。它在通常称为
libGL.so
的共享库中实现,对于 NVIDIA,它是由 NVIDIA 实现的。 - OpenGL 应用程序需要 X display/connection、X 屏幕、X window(或 GLX window),X 颜色图,GLX fbconfig 和 GLX context,然后才能进行第一个 OpenGL 调用。然后在 X window(或 GLX window)上呈现 OpenGL 调用的结果。
- 那个Linux kernel has the DRI, the DRM, and the KMS,貌似比Xlib/XCB/GLX/OpenGL低级,完全不可见(接近GPU驱动的级别,其实我觉得NVIDIA驱动可能会绕过一个一大块内核基础设施?)。
因此,Xlib/XCB 创建 windows,然后 OpenGL 渲染它们。
(OpenGL 无法创建 windows。Xlib/XCB 可以 渲染,但我认为这与 GPU 加速无关。)