]> Git Repo - qemu.git/blob - ui/egl-helpers.c
spice: fix coverity complains
[qemu.git] / ui / egl-helpers.c
1 #include "qemu/osdep.h"
2 #include <glob.h>
3 #include <dirent.h>
4
5 #include "ui/egl-helpers.h"
6
7 EGLDisplay *qemu_egl_display;
8 EGLConfig qemu_egl_config;
9
10 /* ---------------------------------------------------------------------- */
11
12 static bool egl_gles;
13 static int egl_debug;
14
15 #define egl_dbg(_x ...)                          \
16     do {                                         \
17         if (egl_debug) {                         \
18             fprintf(stderr, "egl: " _x);         \
19         }                                        \
20     } while (0);
21
22 /* ---------------------------------------------------------------------- */
23
24 #ifdef CONFIG_OPENGL_DMABUF
25
26 int qemu_egl_rn_fd;
27 struct gbm_device *qemu_egl_rn_gbm_dev;
28 EGLContext qemu_egl_rn_ctx;
29
30 int qemu_egl_rendernode_open(void)
31 {
32     DIR *dir;
33     struct dirent *e;
34     int r, fd;
35     char *p;
36
37     dir = opendir("/dev/dri");
38     if (!dir) {
39         return -1;
40     }
41
42     fd = -1;
43     while ((e = readdir(dir))) {
44         if (e->d_type != DT_CHR) {
45             continue;
46         }
47
48         if (strncmp(e->d_name, "renderD", 7)) {
49             continue;
50         }
51
52         p = g_strdup_printf("/dev/dri/%s", e->d_name);
53
54         r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
55         if (r < 0) {
56             g_free(p);
57             continue;
58         }
59         fd = r;
60         g_free(p);
61         break;
62     }
63
64     closedir(dir);
65     if (fd < 0) {
66         return -1;
67     }
68     return fd;
69 }
70
71 int egl_rendernode_init(void)
72 {
73     qemu_egl_rn_fd = -1;
74
75     qemu_egl_rn_fd = qemu_egl_rendernode_open();
76     if (qemu_egl_rn_fd == -1) {
77         fprintf(stderr, "egl: no drm render node available\n");
78         goto err;
79     }
80
81     qemu_egl_rn_gbm_dev = gbm_create_device(qemu_egl_rn_fd);
82     if (!qemu_egl_rn_gbm_dev) {
83         fprintf(stderr, "egl: gbm_create_device failed\n");
84         goto err;
85     }
86
87     qemu_egl_init_dpy((EGLNativeDisplayType)qemu_egl_rn_gbm_dev, false, false);
88
89     if (!epoxy_has_egl_extension(qemu_egl_display,
90                                  "EGL_KHR_surfaceless_context")) {
91         fprintf(stderr, "egl: EGL_KHR_surfaceless_context not supported\n");
92         goto err;
93     }
94     if (!epoxy_has_egl_extension(qemu_egl_display,
95                                  "EGL_MESA_image_dma_buf_export")) {
96         fprintf(stderr, "egl: EGL_MESA_image_dma_buf_export not supported\n");
97         goto err;
98     }
99
100     qemu_egl_rn_ctx = qemu_egl_init_ctx();
101     if (!qemu_egl_rn_ctx) {
102         fprintf(stderr, "egl: egl_init_ctx failed\n");
103         goto err;
104     }
105
106     return 0;
107
108 err:
109     if (qemu_egl_rn_gbm_dev) {
110         gbm_device_destroy(qemu_egl_rn_gbm_dev);
111     }
112     if (qemu_egl_rn_fd != -1) {
113         close(qemu_egl_rn_fd);
114     }
115
116     return -1;
117 }
118
119 int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc)
120 {
121     EGLImageKHR image;
122     EGLint num_planes, fd;
123
124     image = eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(),
125                               EGL_GL_TEXTURE_2D_KHR,
126                               (EGLClientBuffer)(unsigned long)tex_id,
127                               NULL);
128     if (!image) {
129         return -1;
130     }
131
132     eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc,
133                                   &num_planes, NULL);
134     if (num_planes != 1) {
135         eglDestroyImageKHR(qemu_egl_display, image);
136         return -1;
137     }
138     eglExportDMABUFImageMESA(qemu_egl_display, image, &fd, stride, NULL);
139     eglDestroyImageKHR(qemu_egl_display, image);
140
141     return fd;
142 }
143
144 #endif /* CONFIG_OPENGL_DMABUF */
145
146 /* ---------------------------------------------------------------------- */
147
148 EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
149 {
150     EGLSurface esurface;
151     EGLBoolean b;
152
153     egl_dbg("eglCreateWindowSurface (x11 win id 0x%lx) ...\n",
154             (unsigned long) win);
155     esurface = eglCreateWindowSurface(qemu_egl_display,
156                                       qemu_egl_config,
157                                       (EGLNativeWindowType)win, NULL);
158     if (esurface == EGL_NO_SURFACE) {
159         fprintf(stderr, "egl: eglCreateWindowSurface failed\n");
160         return NULL;
161     }
162
163     b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
164     if (b == EGL_FALSE) {
165         fprintf(stderr, "egl: eglMakeCurrent failed\n");
166         return NULL;
167     }
168
169     return esurface;
170 }
171
172 /* ---------------------------------------------------------------------- */
173
174 int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
175 {
176     static const EGLint conf_att_gl[] = {
177         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
178         EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
179         EGL_RED_SIZE,   5,
180         EGL_GREEN_SIZE, 5,
181         EGL_BLUE_SIZE,  5,
182         EGL_ALPHA_SIZE, 0,
183         EGL_NONE,
184     };
185     static const EGLint conf_att_gles[] = {
186         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
187         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
188         EGL_RED_SIZE,   5,
189         EGL_GREEN_SIZE, 5,
190         EGL_BLUE_SIZE,  5,
191         EGL_ALPHA_SIZE, 0,
192         EGL_NONE,
193     };
194     EGLint major, minor;
195     EGLBoolean b;
196     EGLint n;
197
198     if (debug) {
199         egl_debug = 1;
200         setenv("EGL_LOG_LEVEL", "debug", true);
201         setenv("LIBGL_DEBUG", "verbose", true);
202     }
203
204     egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy);
205     qemu_egl_display = eglGetDisplay(dpy);
206     if (qemu_egl_display == EGL_NO_DISPLAY) {
207         fprintf(stderr, "egl: eglGetDisplay failed\n");
208         return -1;
209     }
210
211     egl_dbg("eglInitialize ...\n");
212     b = eglInitialize(qemu_egl_display, &major, &minor);
213     if (b == EGL_FALSE) {
214         fprintf(stderr, "egl: eglInitialize failed\n");
215         return -1;
216     }
217
218     egl_dbg("eglBindAPI ...\n");
219     b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
220     if (b == EGL_FALSE) {
221         fprintf(stderr, "egl: eglBindAPI failed\n");
222         return -1;
223     }
224
225     egl_dbg("eglChooseConfig ...\n");
226     b = eglChooseConfig(qemu_egl_display,
227                         gles ? conf_att_gles : conf_att_gl,
228                         &qemu_egl_config, 1, &n);
229     if (b == EGL_FALSE || n != 1) {
230         fprintf(stderr, "egl: eglChooseConfig failed\n");
231         return -1;
232     }
233
234     egl_gles = gles;
235     return 0;
236 }
237
238 EGLContext qemu_egl_init_ctx(void)
239 {
240     static const EGLint ctx_att_gl[] = {
241         EGL_NONE
242     };
243     static const EGLint ctx_att_gles[] = {
244         EGL_CONTEXT_CLIENT_VERSION, 2,
245         EGL_NONE
246     };
247
248     EGLContext ectx;
249     EGLBoolean b;
250
251     egl_dbg("eglCreateContext ...\n");
252     ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
253                             egl_gles ? ctx_att_gles : ctx_att_gl);
254     if (ectx == EGL_NO_CONTEXT) {
255         fprintf(stderr, "egl: eglCreateContext failed\n");
256         return NULL;
257     }
258
259     b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx);
260     if (b == EGL_FALSE) {
261         fprintf(stderr, "egl: eglMakeCurrent failed\n");
262         return NULL;
263     }
264
265     return ectx;
266 }
This page took 0.038761 seconds and 4 git commands to generate.