XWayland开发入门系列9.5:第一个EGL窗口

系列索引地址:X11/Wayland开发入门系列教程索引

上一篇:XWayland开发入门系列9:第一个窗口

上一篇文章介绍了如何使用共享内存的方式创建并显示窗口,本文介绍使用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
display = wl_display_connect(0);
if(!display){
printf("Cannot connect to wayland compositor.\n");
return -1;
}

registry = wl_display_get_registry(display);
wl_registry_add_listener(registry,&registry_listener,NULL);

wl_display_dispatch(display);
wl_display_roundtrip(display);

if (compositor == NULL || shell == NULL)
{
fprintf(stderr, "Can't find compositor or shell\n");
return -1;
}else{
fprintf(stderr, "Found compositor and shell\n");
}

surface = wl_compositor_create_surface(compositor);
if (surface == NULL)
{
fprintf(stderr, "Can't create surface\n");
return -1;
}else{
fprintf(stderr, "Created surface\n");
}

shell_surface = wl_shell_get_shell_surface(shell, surface);
wl_shell_surface_set_toplevel(shell_surface);

连接到wayland服务器,创建窗口,还要添加注册捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void registry_handler(void *data,struct wl_registry *registry, uint32_t id,
const char *interface,uint32_t version){
printf("Got a registry event for %s id %d\n", interface, id);
if (strcmp(interface, "wl_compositor") == 0)
{
compositor = wl_registry_bind(registry, id,&wl_compositor_interface,1);
}else if (strcmp(interface, "wl_shell") == 0){
shell = wl_registry_bind(registry, id,&wl_shell_interface,1);
}
}

static void registry_remover(void *data, struct wl_registry *registry, uint32_t id){}

static const struct wl_registry_listener registry_listener= {
registry_handler,
registry_remover
};

窗口显示

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
// init egl
EGLint major, minor, config_count, tmp_n;
EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};

egl_display = eglGetDisplay((EGLNativeDisplayType)display);
eglInitialize(egl_display, &major, &minor);
printf("EGL major: %d, minor %d\n", major, minor);
eglGetConfigs(egl_display, 0, 0, &config_count);
printf("EGL has %d configs\n", config_count);
eglChooseConfig(egl_display, config_attribs, &(egl_config), 1, &tmp_n);
egl_context = eglCreateContext(
egl_display,
egl_config,
EGL_NO_CONTEXT,
context_attribs);

// init window
egl_window = wl_egl_window_create(surface, WIDTH, HEIGHT);
egl_surface = eglCreateWindowSurface(
egl_display,
egl_config,
egl_window,
0);
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);

eglSwapBuffers(egl_display, egl_surface);

获取窗口、初始化、获取配置、选择配置、创建上下文、创建EGL窗口、交换显示缓冲区

具体的到EGL开发系列中再说。

窗口绘制完成后,循环显示窗口

1
2
3
4
5
while (wl_display_dispatch(display) != -1) {
}

// disconnect
wl_display_disconnect(display);

编译运行显示窗口

default

默认为黑色背景,我们调整一下。

可以看到代码中有swapbuffer字样,在标准的OpenGL开发中一般是调用绘图函数,然后使用双缓冲技术交换显示数据。绘制的背景颜色代码应该在此代码的上方。

1
2
glClearColor(0.5f, 0.5f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

将背景设置为棕色

效果为:

colored

可以参考OpenGLut开发入门系列教程索引

总结

我们来看一下调用流程图

flow

这是上一篇共享内存的流程图

flow

可以看到,EGL方式相对简单,代码量少,函数调用少。

完整代码在Wayland_Frashman中的EGL文件夹下的9.5.window_EGL下。

下一篇:XWayland开发入门系列10:shell stable协议