Linux下的OpenGL——Mesa和GLX简介
一.什么是Mesa和GLX
众所周知,OpenGL作为图形界的工业标准,其仅仅定义了一组2D和3D图形接口API,而对于窗口管理、IO消息响应等并没有规定。也就是说,OpenGL依赖各平台提供用于渲染的context以及具体实现方式,而各平台提供的实现不尽相同。这些实现主要有:Windows平台下的WGL、Linux下的Mesa/GLX、Mac OS X下的Cocoa/NSGL,以及跨平台的GLUT、GLFW、SDL等等。
Mesa是Linux下的OpenGL实现。它提供了对AMD Radeon系列、Nvidia GPU、Intel i965, i945, i915以及VMWare虚拟GPU等多种硬件驱动的支持,同时也提供了对softpipe等多种软件驱动的支持。Mesa项目由Brian Paul于1993年8月创建,于1995年2月发布了第一个发行版,此后便受到越来越多的关注,如今Mesa已经是任何一个Linux版本首选的OpenGL实现。
GLX则是在Linux上用于提供GL与窗口交互、窗口管理等等的一组API。它的作用与Windows的WGL、Mac OS X的AGL以及针对OpenGL ES的EGL相似。在Linux上,窗口创建、管理等API遵循X Window接口,而GLX提供了OpenGL与X Window交互的办法。因此GLX也可以运用于其他使用X Window的平台,例如FreeBSD等。
二. Mesa和GLX的安装
在Debian/Ubuntu系统上,我们可以使用以下命令来安装Mesa和GLX:
1 |
sudo apt-get install libgl1-mesa-dev |
如果希望安装OpenGL ES版本的Mesa,那么就是如下命令:
1 |
sudo apt-get install libgles2-mesa-dev |
对于OpenGL ES,EGL的安装如下:
1 |
sudo apt-get install libegl1-mesa-dev |
安装完毕以后,可以使用以下命令查看安装的Mesa版本以及安装是否成功:
1 |
glxinfo | grep "OpenGL version" |
这里我安装完毕后显示的结果是:
1 2 |
szsilence06@ubuntu:~$ glxinfo | grep "OpenGL version" OpenGL version string: 3.0 Mesa 11.2.0 |
三. 第一个Mesa程序
3.1 CMake构建
这里我们采用CMake来构建项目。在CMakeLists.txt内加入如下代码来包含mesa:
1 2 3 4 |
find_package(OpenGL REQUIRED) INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIRS}) LINK_DIRECTORIES(${OPENGL_LIBRARY_DIRS}) |
如下代码负责包含X Window:
1 |
find_package(X11 REQUIRED) |
最后链接库文件:
1 2 3 4 |
target_link_libraries(mesa_test ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ) |
这里mesa_test是我创建的可执行文件名称,读者应当换成自己设定的名称。
3.2 创建窗口
Mesa依赖GLX来为其提供渲染的context。而在继续讨论GLX前,我们需要简单了解一下X Window。X Window支持客户端-服务器模型,也就是说,X Server和X Window可以分别运行于不同的机器上,从而允许我们远程运行桌面系统。因此,在渲染之前,我们必须了解程序将在哪个显示器上进行渲染。
我们可以使用如下函数来获取显示器:
1 |
Display* display = XOpenDisplay(getenv("DISPLAY")); |
当然,在此之前,我们需要包含相应的头文件:
1 2 3 |
#include <GL/gl.h> #include <GL/glx.h> #include <stdlib.h> |
在程序退出前,我们需要关闭到显示器的连接:
1 |
XCloseDisplay(display); |
在获取显示器以后,我们就可以创建窗口了。创建窗口使用XCreateWindow函数,这个函数的原型如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Window XCreateWindow( Display* /* display */, Window /* parent */, int /* x */, int /* y */, unsigned int /* width */, unsigned int /* height */, unsigned int /* border_width */, int /* depth */, unsigned int /* class */, Visual* /* visual */, unsigned long /* valuemask */, XSetWindowAttributes* /* attributes */ ); |
各参数的意义我不列出了,请自行google,这里我给一个简单的调用示例:
1 2 3 4 5 6 7 8 9 |
int screen = DefaultScreen(display); int width = 640; int height = 480; int screen_width = DisplayWidth(display, screen); int screen_height = DisplayHeight(display, screen); window = XCreateWindow(display, XRootWindow(display, screen), (screen_width - width) / 2, (screen_height - height) / 2, width, height, 0, CopyFromParent, InputOutput, DefaultVisual(display, screen), 0, nullptr); |
创建好窗口之后,还要调用以下函数将窗口显示出来:
1 |
XMapWindow(display,window); |
3.3 创建OpenGL环境
有了窗口以后,下一步就是创建context。在创建Context之前,我们需要先对帧缓存进行配置。以下函数可以得到当前屏幕的帧缓存配置信息:
1 2 |
int configNum; GLXFBConfig* config = glXGetFBConfigs(display, screen, &configNum); |
GLXFBConfig是一个包含大量配置项的结构体,configNum即为函数返回的GLXFBConfig中的配置项数目。为简单起见,我这里就不去修改这个config里面的配置项了。然后我们需要从这个配置项建立一个XVisualInfo,这是X Window用来描述显示参数的数据结构:
1 |
XVisualInfo* visualInfo = glXGetVisualFromFBConfig(display, *config); |
然后,我们终于可以创建OpenGL环境了:
1 |
GLXContext context = glXCreateContext(display, visualInfo, nullptr, true); |
最后将该环境设为当前绘制环境:
1 |
glXMakeCurrent(display, window, context); |
3.4 消息循环
熟悉Windows编程的同学应该对消息循环都不陌生。以上我们写好的程序如果运行一下,会发现窗口一闪而过然后程序就退出了。显然这是因为我们还没有为窗口添加消息循环的缘故。
X Window的消息与Windows有一些不同。由于X Window是基于客户端-服务器模型的,因此我们可以自由选择想要处理的消息,这样可以节省网络带宽。以下函数就是负责选择窗口想要处理的消息的:
1 2 3 4 5 |
int XSelectInput( Display* /* display */, Window /* w */, long /* event_mask */ ); |
event_mask有很多种,具体我不列出了。以下代码可以侦听所有的消息:
1 2 |
int event_mask = (1 << 25) - 1; XSelectInput(display, window, event_mask); //listen to all types of events |
设置好要侦听的消息以后,我们可以调用以下函数来获取消息:
1 2 |
XEvent e; XNextEvent(display, &e); |
XNextEvent是一个阻塞式函数,它可以获取XEvent消息。我们可以根据XEvent的type字段判断消息的类型:
1 2 3 |
switch (e.type) { //... } |
各种XEvent中,我们这里需要侦听Expose消息,这个消息在窗口绘制的时候触发,我们应当在这里处理我们的渲染。此外,我们还需要侦听窗口退出消息,好让我们可以进行程序退出前的一些处理操作。然而,X Window标准并没有为窗口退出定义一个消息类型。想要侦听到窗口退出消息的话,一种方法如下所示:
1 2 |
Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, window, &wmDelete, 1); |
这样,当窗口退出时,程序就会发送ClientMessage消息。于是,一个基本的消息循环就如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
bool needQuit = false; while(needQuit == false) { XEvent e; XNextEvent(display, &e); switch (e.type) { case Expose: Render(); break; case ClientMessage: needQuit = true; break; default: break; } } |
3.5 绘制
在以上工作都做好之后,我们就可以按通常的OpenGL编程方式编写绘制代码了。例如,创建好环境以后进行如下初始化设置:
1 2 3 4 5 6 |
glViewport(0, 0, width, height); glClearColor(0, 0, 0, 1); glMatrixMode(GL_PROJECTION); glOrtho(0, width, 0, height, 0, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); |
绘制一个三角形:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void Render() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(400,400); glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(400,200); glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(200,200); glEnd(); glFlush(); glXSwapBuffers(display, window); } |
程序运行结果如图。
3.6 收尾工作
程序退出前要记得以下收尾工作:
1 2 3 |
glXDestroyWindow(display, glxWindow); XDestroyWindow(display, window); XCloseDisplay(display); |
四.总结
本文简要介绍了简要介绍了Linux下OpenGL程序的写法。可以看到这种基于X Window的写法还是很繁琐的,因此如果要做Linux上的图形程序开发的话,还是尽量选用GLUT、GLFW、SDL和Qt这样的封装好的环境比较好。
Linux下的OpenGL——Mesa和GLX简介相关推荐
- Linux中opengl库叫什么名字,Linux下的OpenGL——Mesa和GLX简介
一.什么是Mesa和GLX 众所周知,OpenGL作为图形界的工业标准,其仅仅定义了一组2D和3D图形接口API,而对于窗口管理.IO消息响应等并没有规定.也就是说,OpenGL依赖各平台提供用于渲染 ...
- Linux下Web服务器应用之基础简介
Linux下Web服务器应用之基础简介 一.web服务器基本知识: WWW 是 World Wide Web 的缩写 URL:<协定>://<主机地址或主机名>[:port]/ ...
- LINUX 下构建OpenGL ES 3.0
Ubuntu LINUX 下构建OpenGL ES 3.0 Category : OpenGL LINUX 下构建OpenGL ES 3.0 软件:PowerVRSDKSetup-4.0.run-x6 ...
- Linux下的文件系统与目录系统简介
Linux下的文件系统与目录系统简介 一. 文件系统 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码.SHELL ...
- linux下opengl开发环境,Linux下配置OpenGL开发环境
原创:http://blog..net/u013383042/article/details/50344467 1.首先安装build-essential软件包,输入命令:sudo apt-get i ...
- linux服务器下数学软件下载,Linux下数学(科学)软件简介(一)
装了linux已经有很久了,想着也得用用啊,不然浪费了多不好,以后搞嵌入式的时候还是要用的.很何况linux 就是用C编写的,在哪里编写C/C++那可是很好的,用一个很牛的编译器--GCC. 哈哈!言 ...
- zedboard 音频芯片 adau1761 linux 下音频驱动(一)简介
一.概述 这其实和 ZedBoard 板卡无关,只要音频芯片是 adau1761 ,都可以使用.有两种方法可以驱动此芯片,在此只介绍第二种: 1.Linux uio 方式. 2.本文 adi kern ...
- linux下rpm包和命令使用简介
一.rpm包简介 RPM[1] 是RPM Package Manager(RPM软件包管理器)的缩写,这一文件格式名称虽然打上了RedHat的标志,但是其原始设计理念是开放式的,现在包括OpenLin ...
- linux 下搭建opengl
搭建 OpenGL 的开发环境 学 OpenGL,C/C++ 应该是首选,所以先安装 C/C++ 的开发环境,无论是选择 GCC,还是选择 CLang,在 Ubuntu 中就是一条命令的事,我这里选 ...
最新文章
- 全流程游戏模型制作学习教程
- UpSetR:多数据集绘图可视化处理利器
- 套接字编程--TCP
- Google PageRank的计算源代码
- 使用Win32汇编开发一个dll并在C#中调用
- JS之返回字符首次出现位置的indexOf
- 都2021年了,还不会使用GitHub创建、推送、拉取、克隆远程库、团队协作开发?
- eclipse C/C++开发环境配置全过程
- 如何使用Enigma Recovery检查设备未设置为加密备份
- 牛客网_Wannafly模拟赛1
- 如何使用notepad++查看二进制bin文件
- Oracle 12c升级指南
- Linux ps命令
- Word | 在给毕业论文添加页眉和页脚的时候,如何略过首页和第二页
- 真正手把手教你玩转Git
- Apue学习:高级I/O
- 【Redis】大数据量(百亿级)Key存储需求及解决方案
- HDU 4069 Squiggly Sudoku Dancing-Links(DLX)+Floodfill
- MATLAB处理信号得到频谱、相谱、功率谱
- 【POJ No. 3104】 烘干衣服 Drying
热门文章
- 拉格朗日插值的优缺点_「笔记」拉格朗日插值
- win10 win7 截图快捷键
- 动态 | 腾讯首投国内AI芯片公司,成立仅5个月专注数据中心深度学习芯片
- PLCSIM advanced 和 S7-PLCSIM V17 的区别
- Incorrect date value: ” for column ‘Birthday’ at row 1
- 【Netty】零拷贝(zero-copy)
- ACSI: 360度无死角测量顾客满意度
- 【科创人上海行】扶墙老师王福强:架构师创业要突破思维局限,技术人创业的三种模式,健康第一...
- PDF文件怎么合并?这些方法快来看看
- 如何将CAJ文件转换成PDF格式