Follow Excellent, Success will Chase you

0%

GBM for EGL (Linux)

Mesa GBM (Generic Buffer Manager) basically provides a EGL native window type (just like Wayland and X11), so one could obtain a real EGL surface and create render target buffers. With that then, GL can be used to render into these buffers, which will be shown to the display by queuing a page flip via KMS/DRM API.

用户应用程序直接对内存进行管理,通过EGL可以获取真实的EGL表面并创建渲染目标缓冲区

MESA_platform_gbm

This extension defines how to create EGL resources from native GBM resources using the functions defined by EGL_EXT_platform_base. (GBM is a Generic Buffer Manager for Linux).

离屏渲染–简单示例

https://github.com/elima/gpu-playground/tree/master/render-nodes-minimal

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl31.h>
#include <assert.h>
#include <fcntl.h>
#include <gbm.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

/* a dummy compute shader that does nothing */
#define COMPUTE_SHADER_SRC " \
#version 310 es\n \
\
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; \
\
void main(void) { \
/* awesome compute code here */ \
} \
"

int32_t
main (int32_t argc, char* argv[])
{
bool res;

int32_t fd = open ("/dev/dri/renderD128", O_RDWR);
assert (fd > 0);

struct gbm_device *gbm = gbm_create_device (fd);
assert (gbm != NULL);

/* setup EGL from the GBM device */
EGLDisplay egl_dpy = eglGetPlatformDisplay (EGL_PLATFORM_GBM_MESA, gbm, NULL);
assert (egl_dpy != NULL);

res = eglInitialize (egl_dpy, NULL, NULL);
assert (res);

const char *egl_extension_st = eglQueryString (egl_dpy, EGL_EXTENSIONS);
assert (strstr (egl_extension_st, "EGL_KHR_create_context") != NULL);
assert (strstr (egl_extension_st, "EGL_KHR_surfaceless_context") != NULL);

static const EGLint config_attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
EGL_NONE
};
EGLConfig cfg;
EGLint count;

res = eglChooseConfig (egl_dpy, config_attribs, &cfg, 1, &count);
assert (res);

res = eglBindAPI (EGL_OPENGL_ES_API);
assert (res);

static const EGLint attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLContext core_ctx = eglCreateContext (egl_dpy,
cfg,
EGL_NO_CONTEXT,
attribs);
assert (core_ctx != EGL_NO_CONTEXT);

res = eglMakeCurrent (egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, core_ctx);
assert (res);

/* print some compute limits (not strictly necessary) */
GLint work_group_count[3] = {0};
for (unsigned i = 0; i < 3; i++)
glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT,
i,
&work_group_count[i]);
printf ("GL_MAX_COMPUTE_WORK_GROUP_COUNT: %d, %d, %d\n",
work_group_count[0],
work_group_count[1],
work_group_count[2]);

GLint work_group_size[3] = {0};
for (unsigned i = 0; i < 3; i++)
glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, i, &work_group_size[i]);
printf ("GL_MAX_COMPUTE_WORK_GROUP_SIZE: %d, %d, %d\n",
work_group_size[0],
work_group_size[1],
work_group_size[2]);

GLint max_invocations;
glGetIntegerv (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &max_invocations);
printf ("GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: %d\n", max_invocations);

GLint mem_size;
glGetIntegerv (GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &mem_size);
printf ("GL_MAX_COMPUTE_SHARED_MEMORY_SIZE: %d\n", mem_size);

/* setup a compute shader */
GLuint compute_shader = glCreateShader (GL_COMPUTE_SHADER);

assert (glGetError () == GL_NO_ERROR);
const char *shader_source = COMPUTE_SHADER_SRC;

glShaderSource (compute_shader, 1, &shader_source, NULL);
assert (glGetError () == GL_NO_ERROR);

glCompileShader (compute_shader);
assert (glGetError () == GL_NO_ERROR);

GLuint shader_program = glCreateProgram ();

glAttachShader (shader_program, compute_shader);
assert (glGetError () == GL_NO_ERROR);

glLinkProgram (shader_program);
assert (glGetError () == GL_NO_ERROR);

glDeleteShader (compute_shader);

glUseProgram (shader_program);
assert (glGetError () == GL_NO_ERROR);

/* dispatch computation */
glDispatchCompute (1, 1, 1);
assert (glGetError () == GL_NO_ERROR);

printf ("Compute shader dispatched and finished successfully\n");

/* free stuff */
glDeleteProgram (shader_program);
eglDestroyContext (egl_dpy, core_ctx);
eglTerminate (egl_dpy);
gbm_device_destroy (gbm);
close (fd);

return 0;
}
1
gcc main.c `pkg-config --libs --cflags egl gbm gl`

主要分4部分:

  • 从渲染节点创建GBM设备
  • 设置(无表面的)EGL / OpenGL-ES上下文
  • 创建一个计算着色器程序
  • 调度计算着色器

参考

-------------本文结束感谢您的阅读-------------
  • 本文作者: Winddoing
  • 本文链接: https://winddoing.github.io/post/62365.html
  • 作者声明: 本博文为个人笔记, 由于个人能力有限,难免出现错误,欢迎大家批评指正。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!