1、OpenGL
OpenGL就是 GPU 驱动 的一套标准接口(OpenGL ES 为嵌入式设备 GPU 驱动的标准接口,比如手机, OpenGL ES 全称:OpenGL for Embedded Systems)。
作用:将复杂的、 各种各样的 GPU 硬件包装起来,各个电脑公司编写自家的驱动,然后提供出来 一套统一的接口,供上层软件工程师调用。
2、OpenGL ES
OpenGL ES(OpenGL for Embedded Systems)是一种图形编程接口,专门设计用于嵌入式系统和移动设备,如智能手机、平板电脑和游戏机。它是OpenGL的一个子集,旨在提供高性能的2D和3D图形渲染功能,同时适应了资源受限的嵌入式环境。OpenGL ES有多个版本,包括OpenGL ES 1.x和OpenGL ES 2.0/3.0/3.1/3.2等。这些不同版本提供了不同的功能集。
3、GLX
GLX(OpenGL Extension to the X Window System)是一种用于在X Window System(通常用于Linux和Unix操作系统的图形窗口系统)中与OpenGL图形库集成的扩展。GLX允许OpenGL渲染图形并与X Window System进行交互,以在图形应用程序中创建图形用户界面。
GLX提供了一种方式,让OpenGL应用程序能够在X Window System窗口中进行渲染,同时也可以处理用户输入和窗口管理。这使得开发者可以创建具有3D图形的应用程序,如3D游戏、CAD工具、科学可视化软件等,并在Linux和Unix等系统上运行。 GLX是在X Window System和OpenGL之间的桥梁,使二者协同工作,以实现图形渲染和交互性。
GLX通常通过特定的API调用从应用程序中调用,以便创建OpenGL上下文、管理OpenGL资源、绘制图形和处理用户输入。它是OpenGL在X Window System上的扩展,用于支持图形应用程序的开发和运行。
GLX通常用于传统的桌面系统,如Linux上的X11窗口系统,以支持OpenGL渲染。
4、EGL
EGL(Embedded-System Graphics Library)是一种用于管理图形渲染和窗口系统集成的库,旨在为嵌入式系统和移动设备提供一个通用的图形接口。 EGL是Khronos Group的一个标准,Khronos Group也负责维护OpenGL和Vulkan等图形API标准。
EGL的主要作用是在图形渲染和窗口系统之间提供一个抽象层,以便跨不同平台和设备的图形应用程序能够更容易地开发。它允许图形应用程序与底层图形硬件和操作系统交互,实现窗口的创建、上下文管理、渲染表面的配置,以及与其他图形API(如OpenGL和OpenGL ES)的集成。
EGL通常用于嵌入式系统、移动设备和其他嵌入式图形应用程序中,因为它提供了一种跨平台的方式来处理图形渲染需求,无论是在Android、iOS、Linux、Windows嵌入式系统还是其他平台上。它允许开发者编写与底层硬件和操作系统无关的图形应用程序,从而提高了跨平台兼容性和可移植性。
5、Xorg
Xorg(也称为X.Org)是一个开源的图形服务器软件,用于管理计算机的图形硬件和提供图形用户界面(GUI)的功能。它是X Window System(简称X或X11)的最常用实现之一,X Window System是一个用于 Unix 和类Unix 操作系统的标准图形用户界面协议,在引入MIT-SHM扩展后,允许客户端和X服务器之间通过共享内存交换图形数据。
Xorg 提供了以下主要功能:
图形硬件抽象:Xorg 提供了一个抽象层,允许不同类型的图形硬件(如显卡、显示器)与操作系统和应用程序进行通信,而无需针对特定硬件编写不同的驱动程序。这使得支持多种图形硬件的操作系统和应用程序更容易实现。
窗口系统:Xorg 允许多个图形应用程序在屏幕上共存,每个应用程序在自己的窗口中运行。它提供了窗口管理、窗口排列和交互的基本功能。
图形渲染:Xorg 负责将应用程序生成的图形数据渲染到屏幕上,并处理图形操作,如绘图、移动和调整窗口大小。
输入设备管理:Xorg 管理输入设备,如键盘和鼠标,以便应用程序可以接收用户的输入。
X 协议:Xorg 实现了X协议,这是用于应用程序与X服务器通信的协议。应用程序使用X协议发送图形绘制请求和接收用户输入。
应用程序:
应用程序是用户启动的图形应用,例如终端仿真器、文本编辑器、Web浏览器等。
应用程序创建一个图形窗口,并将其内容(如文本、图像等)绘制到窗口内。
窗口管理器:
窗口管理器是一个特定的X客户端,它具有窗口管理功能,负责管理窗口的外观和行为,包括窗口的排列、位置、大小、最小化、最大化、关闭等操作。
窗口管理器还协调窗口之间的堆叠顺序(Z轴顺序)。
X 服务器(Xserver):
X 服务器是Xorg系统的核心组件,运行在操作系统内核之上。
X 服务器的主要功能包括:接收来自应用程序和窗口管理器的图形绘制请求。
将这些请求翻译为图形操作,并将结果发送到显示设备和硬件驱动程序,以在屏幕上渲染。
处理用户输入,如键盘和鼠标事件,然后将它们传递给相应的应用程序。
管理窗口的排列和Z轴顺序。
提供X协议,使应用程序和窗口管理器能够与X服务器通信。
工作流程如下:
-
- 应用程序绘制其内容,并通过X协议将图形绘制请求发送给X服务器。
- X服务器接收请求,将其转化为图形操作,然后将图形渲染结果显示在屏幕上。
- 窗口管理器控制窗口的外观和行为,以及用户交互操作。
- 用户通过键盘和鼠标与应用程序和窗口管理器互动。
- 应用程序与X服务器通信,窗口管理器是一个特殊的X客户端,也与X服务器通信,而X服务器协调应用程序、窗口管理器和硬件之间的交互。这个模型下,X服务器起到中介作用,协调应用程序和窗口管理器之间的通信,以及与硬件进行通信。
- Wayland
Wayland 是一个用于 Linux 和类 Unix 操作系统的计算机图形协议,它旨在取代传统的 X Window System(X11),提供更现代、高效和安全的图形显示和窗口管理。
架构:Wayland 的设计理念是简化图形栈,消除 X11 中的一些复杂性。它采用了更直接的客户端-服务器架构,其中有两个主要组件:
Wayland 服务器:也称为合成器(Compositor),负责管理图形硬件、窗口的合成和排列,以及用户输入的处理。合成器通常是窗口管理器,但也可以是用于特效和虚拟桌面的组件。有多个合成器可供选择,包括 Weston(Wayland 官方参考实现)以及其他第三方合成器。
Wayland 客户端:应用程序或应用程序的一部分,向服务器发送图形请求并 接收输入事件。客户端使用 Wayland 协议与服务器通信。
共享内存:Wayland 鼓励使用共享内存来传递图形数据,而不是通过网络协议传输数据。这提高了性能,减少了资源开销,尤其适用于高分辨率显示器和多媒体应用程序。通常由 Wayland 协议和合成器(Compositor)进行管理,客户端应用程序不直接进行共享内存操作,而是通过 Wayland 协议进行数据传输。这些细节通常由 Wayland 框架和合成器自动处理。
现代的输入支持:Wayland 提供了更先进的输入系统,特别支持多点触摸和高 DPI 显示器。这有助于改进用户体验,使 Linux 桌面更适用于触摸设备。
安全性:Wayland 强调应用程序的隔离和安全性。每个应用程序运行在自己的独立环境中,无法访问其他应用程序的图形数据。这有助于提高系统的安全性,减少了恶意应用程序的潜在风险。
独立于硬件和操作系统:Wayland 并不依赖于特定的硬件或显示服务器,因此可以在多种硬件架构和操作系统上使用。
- kwin_x11
kwin-x11 是 KDE 桌面环境中用于传统 X11 图形协议的窗口管理器,负责管理窗口的外观和行为。
- kwin_wayland
kwin_wayland 主要在专门设计用于支持 Wayland 协议的桌面环境。与传统的 X11 图形协议相比,Wayland 提供了更现代和高效的图形显示和窗口管理方式。其主要承担以下角色:
1、窗口管理器:
KWin-wayland作为KDE的窗口管理器,负责管理窗口的布局、堆栈顺序、虚拟桌面、窗口装饰(如边框和标题栏),以及提供窗口操作的用户界面(如移动、缩放、最小化、最大化等)
2、合成器:
在wayland下,合成器更为关键,因为它还负责将客户端应用程序渲染的内容绘制到屏幕上。KWin-wayland结合了窗口管理和屏幕合成的功能,允许它提供平滑的动画和高级的桌面效果。
3、wayland会话支持:
当运行在wayland会话中,KWin-wayland也扮演了显示服务器的角色,与应用程序直接交互,管理其绘图表面(surface)并处理输入事件。
kwin-wayland可以理解为融合了X模式下kwin-x11和Xserver的功能。
- mesa与dri框架
Mesa 是一个开源的3D图形库,用于实现OpenGL和其他图形API的支持。它包括了多个组件和模块,用于不同的图形功能。以下是 Mesa 的一些主要组件和包括的内容:
9.1、Mesa层级
- API接口层:
- 这是Mesa的最上层,提供了对外部图形API(如OpenGL、OpenGL ES、Vulkan)的接口。应用程序通过这些API进行图形编程。
- Mesa状态追踪器:
- 对于OpenGL和OpenGL ES,状态追踪器处理API调用、维护图形状态,准备将调用转换为低级操作。
- Mesa驱动层:
- 包括针对特定硬件的硬件加速驱动和软件渲染驱动(如LLVMpipe)。这些驱动将API调用转换为可以由图形硬件执行的命令。
- Gallium3D(部分驱动):
- 对于使用Gallium3D的驱动,这一层提供了一个统一的接口,简化了驱动的开发。
DRI(Direct Rendering Infrastructure)是一个由X.org Foundation提供的框架,用于允许应用程序直接与图形硬件通信,而无需通过X服务器。
9.2、DRI框架层级
- 用户空间DRI驱动:
- 位于Mesa驱动层中,这些驱动是DRI框架的一部分,处理Mesa库的调用并将它们转换为适合硬件的操作。
- DRM(Direct Rendering Manager):
- 位于内核空间,DRM负责管理对图形硬件的直接访问,处理命令提交、内存管理等底层操作。
- 硬件层:
- 图形硬件(如GPU)最终执行渲染操作。
Mesa提供了高层的图形API实现,DRI驱动(作为Mesa驱动的一部分)提供了与特定硬件的接口,而DRM则在内核空间处理硬件级别的直接管理和控制。
Gallium3D属于Mesa驱动层,但它以其独特的架构和方法为驱动的开发提供了不同的途径。Gallium3D驱动和传统的Mesa硬件驱动共同构成了Mesa的驱动层,共同支持广泛的硬件和图形需求。
10、窗口管理器与应用程序的关系举例
QT程序绘制流程示例:
应用程序内部绘制:
应用程序使用Qt框架的QWidget或QGraphicsView等组件创建和绘制图形。
应用程序负责在这些组件上绘制内容,这可以是文本、图像、图形元素等。
窗口管理:
当应用程序创建一个窗口时,KWin会捕获这个窗口,并管理它的外观和行为。
KWin负责窗口的边框、标题栏、按钮(最小化、最大化、关闭)以及窗口的位置和大小。
窗口排列:
KWin管理窗口的排列,以确保它们在屏幕上正确显示,不重叠等。
窗口管理器还维护窗口的Z轴顺序,以确定哪个窗口位于其他窗口的前面。
用户交互:
用户可以与应用程序窗口进行交互,例如拖拽窗口、调整窗口大小、最小化、最大化和关闭等操作。
KWin捕获用户的窗口操作,并根据窗口管理规则处理它们。
总之,KWin管理窗口的外观和行为,以及窗口的布局和用户互动,但不直接管理应用程序内部的绘制逻辑。应用程序自己负责在Qt的Widget上绘制内容,而KWin确保这些窗口在屏幕上以适当的方式显示,并响应用户的操作。这种分工使得应用程序和窗口管理器之间可以协同工作,提供友好的图形用户界面。
- openkylin系统在RISC-V架构上的GPU渲染
1、X11模式
1.1 opengl环境下的渲染工作流程
- 应用程序渲染:
- 应用程序通过GLX在X服务器中创建一个OpenGL上下文。
- 应用程序使用OpenGL API在其OpenGL上下文中进行绘制。
- OpenGL调用通过Mesa和DRI被转换为可以由图形硬件执行的操作。
- 应用程序请求显示渲染结果:
- 应用程序完成渲染后,通过调用glXSwapBuffers向X服务器发起将渲染结果显示到屏幕的请求。
- X服务器接收到请求,并等待GPU渲染完成的通知,这通过DRI2/DRI3协议实现。
- KWin窗口合成:
- KWin作为窗口管理器和合成器,会创建自己的OpenGL上下文用于窗口合成。
- KWin读取各个应用程序窗口(包括通过OpenGL渲染的窗口)的内容,并将它们合成为一个整体的桌面视图。
- 当kwin未开启合成器,则不负责窗口的合成,只负责管理窗口。应用程序自己负责更新自己的渲染显示。
- KWin请求显示合成结果:
- 一旦KWin完成合成,它也可能会使用类似glXSwapBuffers的函数向X服务器发起显示合成结果的请求。
- X服务器再次等待KWin合成操作的渲染完成通知,然后准备显示更新。
- 屏幕显示更新:
- 一旦X服务器接收到GPU完成整个窗口(包括KWin合成的结果)渲染的通知,它将更新屏幕显示,展示最终的桌面视图。
总之,这个过程涉及应用程序和KWin各自进行OpenGL渲染,通过GLX与X服务器交互,并依赖于DRI2/DRI3协议来同步渲染完成的通知。KWin在这个过程中负责合成包括应用程序窗口在内的整个桌面视图,并将最终的合成结果显示到屏幕上。
1.2 opengles环境下的工作流程
在使用OpenGL ES的环境下,尤其是在Linux系统中,渲染流程确实有所不同,主要是在窗口系统接口层面。在这种情况下,通常会使用EGL而不是GLX。EGL提供了一个与窗口系统交互的接口,专门为OpenGL ES(以及其他图形API)设计。以下是在OpenGL ES环境下的渲染流程:
- 应用程序渲染:
- 应用程序通过GLX在X服务器中创建一个OpenGL ES上下文。
- 应用程序使用OpenGL ES API在其OpenGL ES上下文中进行绘制。
- OpenGL ES调用通过Mesa和DRI被转换为可以由图形硬件执行的操作。
- 应用程序请求显示渲染结果:
- 应用程序完成渲染后,通过调用eglSwapBuffers向X服务器发起将渲染结果显示到屏幕的请求。
- X服务器接收到请求,并等待GPU渲染完成的通知,这通过DRI2/DRI3协议实现。
- KWin窗口合成:
- KWin作为窗口管理器和合成器,会创建自己的OpenGL ES上下文用于窗口合成。
- KWin读取各个应用程序窗口(包括通过OpenGL ES渲染的窗口)的内容,并将它们合成为一个整体的桌面视图。
- 当kwin未开启合成器,则不负责窗口的合成,只负责管理窗口。应用程序自己负责更新自己的渲染显示。
- KWin请求显示合成结果:
- 一旦KWin完成合成,它也可能会使用类似eglSwapBuffers的函数向X服务器发起显示合成结果的请求。
- X服务器再次等待KWin合成操作的渲染完成通知,然后准备显示更新。
- 屏幕显示更新:
- 一旦X服务器接收到GPU完成整个窗口(包括KWin合成的结果)渲染的通知,它将更新屏幕显示,展示最终的桌面视图。
在OpenGL ES环境中,EGL替代了GLX作为窗口系统接口,但整体渲染流程保持相似:应用程序和窗口管理器(如KWin)都进行自己的渲染,并通过EGL与X服务器交互来管理显示。EGL为OpenGL ES提供了与原生窗口系统交互所需的功能,使得它能够更好地适用于OpenGL ES和其他现代图形API。
- wayland模式
在wayland模式下,opengl和opengles渲染的工作流程一致,基本流程如下:
- 应用程序渲染:
- 应用程序通常使用EGL(而非GLX)创建和管理OpenGL或OpenGL ES上下文。
- 应用程序在其上下文中使用OpenGL或OpenGL ES API进行绘制。
- 渲染命令依然通过Mesa和DRI转换为硬件可执行的操作。
- 应用程序请求显示渲染结果:
- 应用程序完成渲染后,通过EGL的eglSwapBuffers接口提交其渲染结果。
- 在Wayland中,应用程序通常直接与合成器(如KWin)交互,而非传统的X服务器。
- KWin作为合成器:
- 在Wayland下,KWin不仅是窗口管理器,还是显示服务器和合成器,Wayland模式下不支持关闭合成模式,合成是其窗口管理的核心组成部分。
- KWin直接负责接收应用程序的渲染结果,并将它们合成为整体的桌面视图。
- KWin显示合成结果:
- KWin负责将合成后的桌面视图显示到屏幕上。
- 这个过程不需要通过传统的X11交互,而是KWin直接与显示硬件协作。
- 屏幕显示更新:
- 在Wayland中,屏幕的显示更新是由合成器(如KWin)直接控制,它基于接收到的各个应用程序的渲染结果更新屏幕。
三、opengl/opengles上下文与X11窗口的关联
在X11环境中,将EGL与已由X11创建的窗口关联的过程主要涉及以下步骤:
- 创建X窗口:
- 首先,使用X11 API(如Xlib或XCB)创建一个窗口。这个步骤涉及定义窗口的大小、位置、视觉属性等。
- 获取X窗口的窗口ID:
- 创建窗口后,您会获得一个窗口ID(通常是一个Window类型的值),这个ID唯一标识了在X服务器中创建的窗口。
- 初始化EGL:
- 接下来,初始化EGL环境。这通常包括获取EGL显示连接(通常与X服务器的连接关联),并选择合适的EGL配置。
- 创建EGL表面:
- 使用前面获取的X窗口ID创建一个EGL表面(surface)。这一步是将EGL与X窗口关联的关键。在EGL中调用eglCreateWindowSurface函数,并传入EGL显示连接、选择的EGL配置以及X窗口ID作为参数。
- 创建并绑定EGL上下文:
- 创建一个EGL上下文(使用eglCreateContext),然后将该上下文绑定到前面创建的EGL表面。这使得您可以在该表面上进行OpenGL ES渲染。
- 进行OpenGL ES渲染:
- 在绑定了EGL上下文的表面上,您现在可以使用OpenGL ES API进行渲染了。渲染的结果将显示在关联的X窗口上。
- 交换缓冲区:
- 完成渲染后,使用eglSwapBuffers将渲染的内容显示到窗口上。这个调用会将渲染结果从后台缓冲区交换到前台,使其在屏幕上可见。
通过上述步骤,EGL有效地与X11窗口系统协作,使OpenGL ES渲染内容能够在X窗口中正确显示。这种机制提供了一种在X11环境下使用现代OpenGL ES API的方式。
使用GLX在X11环境中创建和关联OpenGL上下文的过程:
- 创建X窗口:
- 与EGL一样,首先需要使用X11 API创建一个窗口。这包括定义窗口的大小、位置、视觉属性等。
- 获取X窗口的窗口ID:
- 创建窗口后,你会得到一个窗口ID,这是X服务器中该窗口的唯一标识符。
- 初始化GLX:
- 获取与X服务器的连接,并选择合适的视觉配置(如颜色深度、双缓冲等)。
- 创建GLX渲染上下文:
- 使用glXCreateContext或相关函数创建一个OpenGL渲染上下文。这个上下文保存了OpenGL的所有状态和资源。
- 创建GLX窗口:
- 创建一个与X窗口关联的GLX窗口或“绘图表面”。这通常通过调用glXCreateWindow实现,它将X窗口ID作为参数。
- 绑定上下文到窗口:
- 使用glXMakeCurrent将上下文与GLX窗口(和因此与X窗口)关联起来。这使得在该上下文中的OpenGL渲染会显示在指定的X窗口上。
- 进行OpenGL渲染:
- 在绑定了上下文的窗口上,可以使用OpenGL API进行渲染。渲染的结果将显示在X窗口上。
- 交换缓冲区:
- 使用glXSwapBuffers来交换前后缓冲区,将渲染结果显示到屏幕上。
GLX与EGL的比较
- 不同的窗口系统接口:虽然GLX和EGL的基本目的相同(即在特定窗口上提供OpenGL渲染能力),但它们是为不同的图形API设计的。GLX专门为传统的OpenGL设计,而EGL为OpenGL ES和其他现代图形API(如Vulkan)设计。
- 不同的API和过程:GLX和EGL使用的API不同,反映了它们各自的设计和适用的图形API的不同。
总体而言,GLX提供了一种在X11环境中使用传统OpenGL的方式,而EGL则为使用OpenGL ES(以及其他现代图形API)提供了窗口系统接口。