XOpenGL入门教程1:空白窗口

系列索引:XOpenGL入门教程索引

第一步,先显示一个简单的界面。

函数处理流程图

flowchart TB
  D --> initializeEGL
  E --> mainloop
  F --> destroyEGL
  subgraph init
    direction TB
    A[XOpenDisplay] --> B[XCreateSimpleWindow]
    B --> C[XMapWindow]
    C --> D[initializeEGL]
    D --> E[mainloop]
    E --> F[destroyEGL]
    F --> G[XDestroyWindow]
    G --> H[XCloseDisplay]
  end
  subgraph initializeEGL
    direction TB
    I[eglGetDisplay] --> J[eglInitialize]
    J --> K[eglChooseConfig]
    K --> L[eglCreateContext]
    L --> M[eglCreateWindowSurface]
    M --> N[eglMakeCurrent]
  end
  subgraph mainloop
    direction TB
    O[XPending] --> P[eglSwapBuffers]
  end
  subgraph destroyEGL
    direction TB
    Q[eglDestroyContext] --> R[eglDestroySurface]
    R --> S[eglTerminate]
  end

核心

先是X11相关的部分。连接显示服务器,创建新窗口、循环显示、释放内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int main(int argc, char *argv[])
{
Display *xdisplay = XOpenDisplay(nullptr);
if (xdisplay == nullptr) {
fprintf(stderr, "XOpenDisplay failed\n");
return EXIT_FAILURE;
}

Window xwindow = XCreateSimpleWindow(xdisplay, DefaultRootWindow(xdisplay), 100, 100, 640, 480,
1, BlackPixel(xdisplay, 0), WhitePixel(xdisplay, 0));
XMapWindow(xdisplay, xwindow);

EGLDisplay display = nullptr;
EGLContext context = nullptr;
EGLSurface surface = nullptr;
if (!initializeEGL(xdisplay, xwindow, &display, &context, &surface)) {
return EXIT_FAILURE;
}

mainloop(xdisplay, display, surface);

destroyEGL(&display, &context, &surface);
XDestroyWindow(xdisplay, xwindow);
XCloseDisplay(xdisplay);

return EXIT_SUCCESS;
}

初始化EGL

本部分是本系列的核心,即EGL相关部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
bool initializeEGL(EGLNativeDisplayType nativedisplay, EGLNativeWindowType nativewindow, EGLDisplay *display, EGLContext *context, EGLSurface *surface)
{
*display = eglGetDisplay(nativedisplay);
if (*display == EGL_NO_DISPLAY) {
fprintf(stderr, "eglGetDisplay failed: %d\n", eglGetError());
return false;
}

if (!eglInitialize(*display, nullptr, nullptr)) {
fprintf(stderr, "eglInitialize failed: %d\n", eglGetError());
return false;
}

EGLint attr[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
EGL_BUFFER_SIZE, 32,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE};
EGLConfig config = nullptr;
EGLint numConfigs = 0;
if (!eglChooseConfig(*display, attr, &config, 1, &numConfigs)) {
fprintf(stderr, "eglChooseConfig failed: %d\n", eglGetError());
return false;
}
if (numConfigs != 1) {
fprintf(stderr, "eglChooseConfig failed (numConfigs must be 1 but %d): %d\n", numConfigs, eglGetError());
return false;
}

*surface = eglCreateWindowSurface(*display, config, nativewindow, nullptr);
if (*surface == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreateWindowSurface failed: %d\n", eglGetError());
return false;
}

EGLint ctxattr[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE};
*context = eglCreateContext(*display, config, EGL_NO_CONTEXT, ctxattr);
if (*context == EGL_NO_CONTEXT) {
fprintf(stderr, "eglCreateContext failed: %d\n", eglGetError());
return false;
}

if (!eglMakeCurrent(*display, *surface, *surface, *context)) {
fprintf(stderr, "eglMakeCurrent failed: %d\n", eglGetError());
return false;
}

return true;
}

循环

1
2
3
4
5
6
7
8
9
10
void mainloop(Display *xdisplay, EGLDisplay display, EGLSurface surface)
{
for (;;) {
XPending(xdisplay);
//glClearColor(0.25f, 0.25f, 0.5f, 1.0f);
//glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(display, surface);
usleep(1000);
}
}

释放

1
2
3
4
5
6
void destroyEGL(EGLDisplay *display, EGLContext *context, EGLSurface *surface)
{
eglDestroyContext(display, context);
eglDestroySurface(display, surface);
eglTerminate(display);
}

显示

编译运行

1
g++ blank.cpp -lEGL -lX11 -o blank

效果为

空白窗口

代码中并没有窗口边框和右上角的按钮,这些是X11桌面环境提供的。

窗口关闭后会提示有窗口从X11服务器手动退出了。

下一篇:XOpenGL入门教程2:版本信息


XOpenGL入门教程1:空白窗口
https://blog.jackeylea.com/xopengl/xopengl-blank-window/
作者
JackeyLea
发布于
2022年9月10日
许可协议