]>
Commit | Line | Data |
---|---|---|
1 | // based on | |
2 | // https://www.khronos.org/registry/EGL/extensions/MESA/EGL_MESA_platform_gbm.txt | |
3 | ||
4 | #include <stdio.h> | |
5 | #include <stdlib.h> | |
6 | #include <string.h> | |
7 | #include <unistd.h> | |
8 | ||
9 | #include <sys/types.h> | |
10 | #include <sys/stat.h> | |
11 | #include <fcntl.h> | |
12 | ||
13 | #include <gbm.h> | |
14 | #include <EGL/egl.h> | |
15 | #include <EGL/eglext.h> | |
16 | #include <GLES2/gl2.h> | |
17 | ||
18 | struct my_display { | |
19 | struct gbm_device *gbm; | |
20 | EGLDisplay egl; | |
21 | }; | |
22 | ||
23 | struct my_config { | |
24 | struct my_display dpy; | |
25 | EGLConfig egl; | |
26 | }; | |
27 | ||
28 | struct my_window { | |
29 | struct my_config config; | |
30 | struct gbm_surface *gbm; | |
31 | EGLSurface egl; | |
32 | }; | |
33 | ||
34 | PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT; | |
35 | PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurfaceEXT; | |
36 | ||
37 | static void | |
38 | check_extensions(void) | |
39 | { | |
40 | const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | |
41 | ||
42 | if (!client_extensions) { | |
43 | abort(); | |
44 | } | |
45 | if (!strstr(client_extensions, "EGL_MESA_platform_gbm")) { | |
46 | abort(); | |
47 | } | |
48 | ||
49 | if (!strstr(client_extensions, "EGL_EXT_platform_base")) { | |
50 | abort(); | |
51 | } | |
52 | ||
53 | getPlatformDisplayEXT = | |
54 | (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); | |
55 | createPlatformWindowSurfaceEXT = | |
56 | (void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); | |
57 | ||
58 | } | |
59 | ||
60 | static struct my_display | |
61 | get_display(void) | |
62 | { | |
63 | struct my_display dpy; | |
64 | EGLint major, minor; | |
65 | ||
66 | int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC); | |
67 | if (fd < 0) | |
68 | abort(); | |
69 | ||
70 | dpy.gbm = gbm_create_device(fd); | |
71 | if (!dpy.gbm) | |
72 | abort(); | |
73 | ||
74 | dpy.egl = getPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy.gbm, NULL); | |
75 | ||
76 | if (dpy.egl == EGL_NO_DISPLAY) | |
77 | abort(); | |
78 | ||
79 | if (eglInitialize(dpy.egl, &major, &minor)) | |
80 | printf ("EGL %d.%d\n", major, minor); | |
81 | else | |
82 | abort(); | |
83 | ||
84 | return dpy; | |
85 | } | |
86 | ||
87 | static struct my_config | |
88 | get_config(struct my_display dpy) | |
89 | { | |
90 | struct my_config config = { | |
91 | .dpy = dpy, | |
92 | }; | |
93 | ||
94 | EGLint egl_config_attribs[] = { | |
95 | EGL_BUFFER_SIZE, 32, | |
96 | EGL_DEPTH_SIZE, EGL_DONT_CARE, | |
97 | EGL_STENCIL_SIZE, EGL_DONT_CARE, | |
98 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
99 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | |
100 | EGL_NONE, | |
101 | }; | |
102 | ||
103 | EGLint num_configs; | |
104 | if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) | |
105 | abort(); | |
106 | ||
107 | EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig)); | |
108 | if (!eglChooseConfig(dpy.egl, egl_config_attribs, | |
109 | configs, num_configs, &num_configs)) { | |
110 | abort(); | |
111 | } | |
112 | if (num_configs == 0) | |
113 | abort(); | |
114 | ||
115 | for (int i = 0; i < num_configs; ++i) { | |
116 | EGLint gbm_format; | |
117 | struct gbm_format_name_desc desc; | |
118 | ||
119 | if (!eglGetConfigAttrib(dpy.egl, configs[i], | |
120 | EGL_NATIVE_VISUAL_ID, &gbm_format)) { | |
121 | abort(); | |
122 | } | |
123 | ||
124 | printf ("found gbm_format: %s\n", gbm_format_get_name (gbm_format, &desc)); | |
125 | if (gbm_format == GBM_FORMAT_ARGB8888) { | |
126 | config.egl = configs[i]; | |
127 | free(configs); | |
128 | return config; | |
129 | } | |
130 | } | |
131 | ||
132 | // no egl config matching gbm format | |
133 | abort(); | |
134 | } | |
135 | ||
136 | static struct my_window | |
137 | get_window(struct my_config config) | |
138 | { | |
139 | struct my_window window = { | |
140 | .config = config, | |
141 | }; | |
142 | ||
143 | window.gbm = gbm_surface_create(config.dpy.gbm, | |
144 | 256, 256, | |
145 | GBM_FORMAT_XRGB8888, | |
146 | GBM_BO_USE_RENDERING); | |
147 | if (!window.gbm) | |
148 | abort(); | |
149 | ||
150 | window.egl = createPlatformWindowSurfaceEXT(config.dpy.egl, | |
151 | config.egl, | |
152 | window.gbm, | |
153 | NULL); | |
154 | if (window.egl == EGL_NO_SURFACE) | |
155 | abort(); | |
156 | ||
157 | return window; | |
158 | } | |
159 | ||
160 | int | |
161 | main(void) | |
162 | { | |
163 | check_extensions(); | |
164 | ||
165 | struct my_display dpy = get_display(); | |
166 | struct my_config config = get_config(dpy); | |
167 | struct my_window window = get_window(config); | |
168 | EGLContext context; | |
169 | ||
170 | context = eglCreateContext(dpy.egl, config.egl, EGL_NO_CONTEXT, NULL); | |
171 | eglMakeCurrent(dpy.egl, window.egl, window.egl, context); | |
172 | ||
173 | /* just so we have some gles symbols too */ | |
174 | glClearColor(1.0, 1.0, 1.0, 1.0); | |
175 | glClear(GL_COLOR_BUFFER_BIT); | |
176 | glFlush(); | |
177 | ||
178 | return EXIT_SUCCESS; | |
179 | } |