远程显示设备
继续上一篇,使用EGL创建surface之后,就可以进行编译和执行了
# 编译链接
gcc -o example example.c -lEGL
# 执行
./example
如果程序马上执行结束,就是属于正常的,如果程序卡在那里不动也没有结束,就说明还有问题,可能是在寻找显示设备DISPLAY,但是寻找不到就卡在那里。EGL创建的surface会绑定到一个默认显示设备上,而linux中可以通过设置DISPLAY变量来指定显示设备,同时也可以将显示设备设置为一个远程显示器,这样可以通过远程网络进行显示。
# 在~/.bashrc文件中设置DISPLAY
export DISPLAY=IP:0.0
# 之后执行source ~/.bashrc
这样可以在windows上远程显示出来,这里可以使用putty和Xming软件进行远程显示,这样操作完成之后,程序就应该可以正常执行了。
除了使用Xming还可以使用VNCserver来进行远程显示
yum install tigervnc-server
yum install tigervnc
# 设置密码
vncserver
然后在windows端安装vncviewer或者tightvnc,就可以远程连接登录linux系统了,vncserver桌面删除命令如下所示。
# 删除桌面
vncserver kill :1
但是需要注意的是,这种远程显示是直接发送绘图指令的,常规的绘图指令比如打开一个桌面或者软件界面,都是没有问题的。但是如果要操纵更加复杂的底层绘图指令,比如使用opengl的freeglut库的glut函数来创建窗口或者缓存等,会调用基于X11的GLX库,但是windows的窗口系统没有GLX库,那么程序就会运行失败。
在多个显卡中指定显示设备
如果linux系统上有多个显卡,可以指定某个显卡为显示设备
#define EGL_EGLEXT_PROTOTYPES
#include <EGL/egl.h>
#include <EGL/eglext.h>
main()
{
static const int MAX_DEVICES = 4;
EGLDeviceEXT eglDevs[MAX_DEVICES];
EGLint numDevices;
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =
(PFNEGLQUERYDEVICESEXTPROC)
eglGetProcAddress("eglQueryDevicesEXT");
eglQueryDevicesEXT(MAX_DEVICES, eglDevs, &numDevices);
printf(“Detected %d devices\n”, numDevices);
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)
eglGetProcAddress("eglGetPlatformDisplayEXT");
eglDpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
eglDevs[0], 0);
// ...
}
创建窗口
使用EGL创建一个窗口的简单流程是
eglGetDisplay()
eglInitialize()
eglChooseConfig()
eglCreateWindowSurface()
eglCreatePBufferSurface()
eglCreatePixmapSurface()
# draw with GL
eglSwapBuffers()
其中第一种是可以直接显示在屏幕上的surface类型,
EGLSurface eglCreateWindowSurface()
而另外两种surface类型则不会直接显示在屏幕上,分别是
eglCreatePBufferSurface()
eglCreatePixmapSurface()
通过查询函数文档,知道其调用方式是
EGLSurface eglCreateWindowSurface( EGLDisplay display,
EGLConfig config,
NativeWindowType native_window,
EGLint const * attrib_list);
管理你自己的OpenGL资源
在之前的例子中,使用EGL创建Pbuffer Surface,并用EGL管理所有的Buffer,这个类似于窗口中默认的Framebuffer。也可以你自己管理OpenGL资源,这时就要跳过函数eglCreatePbufferSurface(),之后要出创建OpenGL Context,并且要通过一个函数绑定
eglMakeCurrent(eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, eglCtx);
之后就要自己创建一个Frame Buffer Object (FBO),然后绑定纹理和渲染缓存,这点是很有用的,可以避免从EGL Surface拷贝数据到CUDA/OpenGL加速缓存。