OpenGL是否使用Xlib来绘制窗口并渲染事物,还是反过来?

时间:2016-11-10 20:38:46

标签: opengl graphics fonts x11

我想使用 OpenGL Xlib 在窗口上渲染字体和线条,但我想知道哪一个是"更多根本"

使用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来显示窗口并渲染字体/几何图元?或者是相反的方式?

如果我想要更多&#34;低水平&#34;我应该使用哪一个?控制渲染和显示?

编辑:

我的目标应用程序是一个准系统文本编辑器,它只渲染位图字体,只有255种颜色,只进行软件渲染(即假设没有GPU)。

我尝试过 Cairo / Pango SDL2 GTK Qt ,但他们的速度很慢与纯Xlib相比没有反应。

3 个答案:

答案 0 :(得分:13)

警告:文字墙已进入!

@sourcejedi已经给出了答案,但其中有一些不准确之处 - 这并不会造成伤害,但可能会令人困惑。

首先,OpenGL和Xlib彼此正交。两者都不依赖于另一个,你可以独立使用它们。 GLX对Xlib有依赖(如果你想要GLX,为什么你不能完全抛弃Xlib而支持Xcb),但是依赖的表面积足够小,因此您可以在大多数情况下使用Xcb,并在必须使用GLX的少数部分使用Xlib-on-Xcb包装器。现在我在这里删除了一些缩略词,所以让我们先对它们进行分类:

Xlib&amp; Xcb都是实现X11协议的客户端的库。从技术上讲,你可以通过实现协议&#34;你自己&#34; (事实上​​,正在不断努力从同样的规范文件中自动生成Haskell代码,这些文件也用于生成Xcb代码)。 X11是通过套接字传输的,所以如果你能以某种方式转移那个套接字和绑定之间的某些内部状态,你甚至可以混合和匹配绑定,如果你小心你去哪里。

OpenGL本身是一个纯粹的低级别(它提供的基本意义上的低级别:点,线和三角形)绘图工具,并且没有&#34; windows&#34;在里面。通过引入framebuffer对象,原则上您可以创建无头OpenGL上下文并完全在自我管理的图像表面的范围内操作。但是经常(但肯定不总是)你希望你的图画能够立即显示在显示器上。这就是窗口系统接口(WSI)发挥作用的地方。 OpenGL因此围绕它的整个支持结构已经很老了,所以对整个WSI业务并没有太多的考虑,这导致了一个相当好的......实际上没有一个干净定义的接口。所有,到目前为止,一切都发生在环境中。通常的方式是&#34;在这里我已经有了一些预先存在的显示系统图像表面,我可以在那上面隐藏OpenGL吗?&#34; 这让我们很喜欢用于OpenGL的ad-hoc窗口系统API。用于X11的GLX和用于Win32的WGL; Apple是它自己的整个章节......

GLX是两件事:首先它是X11扩展,即它使用X11传输为X11服务器中的一组新命令创建一个通道。这些命令是版本1.1到2.1中指定的OpenGL函数(尚未为3.x向前指定GLX)。在这方面,GLX在X11服务器端放置一个OpenGL实现,GLX操作码用于向运行服务器端的OpenGL上下文进行远程过程调用。 第二个 GLX客户端实现,它位于libGL.so OpenGL API访问库中。

除此之外,GLX还实现了一些便利性。功能,比如创建列出OpenGL显示列表的rasterop&#34;字体&#34;来自X11服务器端字体;仅适用于以前使用X11核心的旧版位图字体。在低像素密度显示器上没有抗锯齿性并且看起来不是特别好(如果你有一个高像素密度输出设备,你可以在没有抗锯齿的情况下逃脱,高分辨率位图字体实际上看起来很棒,例如:激光打印机)。 WGL遵循GLX的领先优势,并为Windows位图字体做了同样的事情。这是唯一的&#34;种类的&#34;字体渲染支持直接构建到OpenGL生态系统中。但对于7位可打印ASCII集之外的任何内容,它几乎没用。它完全没有布局引擎来正确格式化文本(左,右,中心对齐,对齐或其他)。它完全依赖于显示列表和OpenGL光栅操作,这些操作有类似于#34的注意事项;如果第一个角色的起始位置恰好位于视口之外,那么整个事情甚至不会去工作&#34;。因此,即使尝试使用它也不会感到烦恼。

使用GLX,您可以使用现有的X11窗口并发送设置此窗口的X11服务器命令以用于OpenGL。同样使用GLX,您可以发送X11服务器命令,要求它创建OpenGL上下文。 OpenGL上下文与特定的X11 drawable无关。您可以自由地附加和分离它,只要您想要附加它的可绘制与该上下文兼容(即已针对特定帧缓冲区格式配置,该上下文期望它的主帧缓冲区)。然后当你进行OpenGL调用时,GLX将它们包装成操作码并通过套接字连接发送到它们执行的X11服务器。

当然,所有de / /序列化都会产生一些非显着的执行成本,因此很快就会引入一种名为&#34; direct context&#34; 的特殊模式,其中GLX / X11服务器组合仅用于设置OpenGL上下文并使其在X11 drawable上是最新的,其余程序直接针对OpenGL实现,从而避免所有序列化甚至直接访问地址批量数据对象(纹理,缓冲区对象等)所在的空间。这就是为什么在基于X11的环境中,您可以找到实际存在于两个进程中的相同直接连接上下文的OpenGL实现实例:X11服务器和使用它的客户端。

正如我上面提到的Xlib,Xcb&amp; co只是X11协议的客户端实现。 X11的服务器端提供了一组基本的图形功能。 X11核心具有一些有限的位图字体绘制功能,以及绘制点,线,弧,(圆角)矩形,圆和多边形的功能。用实心笔或阴影图案进行绘图和填充;没有插值或渐变。根据您想要绘制的图像类型,这是相当有限的。在2000年到2010年之间,每个人都想画出色彩丰富的用户界面,有很多渐变和花哨的边框和诸如此类的东西(我个人从来都不喜欢那些),但在过去几年中,半/平面UI设计已经成为一种趋势,你可以实际绘制的与X11核心(没有抗锯齿文本)。最终人们希望能够绘制渐变X11方面,因此引入了XRender扩展,它为您提供了基本上相当于OpenGL的GL_TRIANGLES原语的2D,没有着色器,纹理和照明;你会得到颜色插值,渐变和抗锯齿。作为一个侧面的Xft库(重要的,那个库,而不是X11服务器的东西),是在XRender上创建的,它可以将一堆客户端光栅化字体字形加载到服务器上,这样你就可以将它们加载到服务器上了。可绘制的&#34; antialiased&#34;文本。这是关于X11服务器的绘图功能。 这些绘图功能如何在X11服务器中实际实现是未指定的,完全取决于实现,更重要的是依赖于设备相关的X代码(DDX),即X图形驱动程序!它可以完全在软件(通常是这种情况,目前通过基于pixman渲染库的服务器端组件),但GPU加速甚至基于在服务器端部分使用的OpenGL实现(魅力)。< / p>

  

如果我想要更多&#34;低水平&#34;我应该使用哪一个?控制渲染和显示?

这完全取决于您的目标应用程序。

如果您的目标是做一些不做大量图形图形处理的事情(文本编辑器,聊天程序等)并且您可以与X11绑定,那么可能是X11通过Xlib或Xcb。最重要的是,X11为您提供的东西假装是中途合理的文本绘图功能,至少可以以可预测的方式工作。

如果你的目标是进行图形图形工作(图像处理,CAD,桌面出版,还有网络浏览器),那么OpenGL是正确的选择,但这意味着你在你的自己的&#34;任何超越点,线和三角形的东西。

这些天实际上存在GPU。 10年前,并没有那么多,所以当时开发的UI工具包和图形后端(我们仍在使用它们)将完全用软件在CPU上完成大部分工作,并将最终图像传输到显示设备。这是合理的。如果最终目标是可再现的,高质量的图形仍然存在,因为GPU为性能削减了很多角落而且行为不一样(OpenGL要求在同一个上下文中渲染相同操作链的结果为1 :1匹配,但只更改一位,所有投注都已关闭。

现在可以在现代Linux(!)系统上找到三个渲染库(一般不是X11!),可以使用#34;独立&#34; Cairo Anti-Grain-Geometry(AGG) pixman 。 Cairo主要由基于GDK / GTK +的程序使用,pixman在X11服务器中使用(但您也可以在程序中使用它)。 AGG尤其不是工具包的主要图形工具包,但是被许多程序和库使用(最值得注意的是绘图,如matplotlib)。人们也不能忘记&#34;光栅&#34; Qt中的图形引擎,但只能在QPainter中的Qt中使用(如果您的程序使用Qt,则可以单独使用,但不能在没有Qt的情况下使用)。

对于开罗而言,AGG与开罗的最大卖点是,它有一个纯粹的C绑定。不幸的是,开罗不是一个非常快速的渲染器(它在过去10年取得了巨大进步)。但它吃的是AGG的尘埃,它更快,而且(具有讽刺意味)也可以产生更好的质量;不幸的是AGG是一个C ++库,所以为了有效地使用它,你必然会使用C ++,这是一个缺点。几年前,AGG的主要开发人员遗憾地去世了,这使得开发停滞了一段时间,但它再次被社区所接受。

答案 1 :(得分:1)

Xlib绘图命令通过网络套接字发送 obsolete 请求。原始绘图命令已过时,例如当前工具包不使用特定于文本的X请求。看起来仍然使用(抗锯齿)XRender扩展。 X服务器可以使用它喜欢的任何方法实现请求。请参阅:魅力,使用opengl实现的XRender。

OpenGL同样是一个API,而不是一个特定的实现。

  • 它是在不依赖X11的平台上实现的,包括Windows。 (在这种情况下,X11可用作第三方软件)。
  • 它也在Wayland上实现,Wayland是Linux上X11的继承者,否则与XRender无关。
  • 当opengl硬件加速不可用时,opengl可能会以软件呈现。

这个问题没有答案,你可以很容易地构建在两种方式之间工作的情况,或者两者中只有一种可用的情况,或两者都实现硬件加速而不使用另一种情况等的情况。

OpenGL可以访问更多GPU功能,例如:着色器编程。从这个意义上讲,它可以更全面地控制硬件。

除此之外:opengl有一个文本绘图api ??我很困惑。

此问题的作者可能打算包含linux标记。

快速谷歌搜索,我发现的最新文章here。我希望在某个地方有更好的表现。还有GLX

上的维基百科页面

答案 2 :(得分:1)

无论您最终使用的图像引擎(也不要忘记Wayland!),您想要与harbuzz-ng,freebidi,fontconfig和freetype进行对话。 Unicode和Opentype现在移动速度如此之快,自己重新实现相应的引擎并不是很有趣。

您可能认为7位ascii就足够了,但即使嵌入式设备现在也能做得更多(如果只是为了呈现i18n流,音乐标签等)。

Pango-Cairo曾经是整合所有这些的标准方式。但是现在许多大型应用程序正在向skia转移速度。