ui: misc fixes which piled up during 3.0 release freeze

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJbg7vzAAoJEEy22O7T6HE4ipQQAJ9KnrLLr23moSW+RwMjNbma
 m0ZK1ySWwRTFLcfvW2mREKW7smeRWRXILrD0KH8OYNf+AIqXzbVo160lV1LnWYLO
 9VtwGUsUpy36hYlBbc1ZwW9d0vZ8suF2j1k5uESUS8ZJg9QczyPGYWaa4Be9pC7y
 tIud4iPcukSnM42bF9EZCmUdi5rxhqBN6rLZtE/Bg+B7JJAxIh3fR4c2Bi27o1d4
 RX4gyoyl7WQmN77ejmZBelEQsUYWLFDrK1RL5Ir8Ib0O0mzSm7fnJQ5WgYv8R8Na
 wTS1t+ue7wa8GGQonUwRl5ttVf0BppvOu5NZLFaQyCVODTgjVO/IjbKpkijBgHsB
 DqOh4bYK8CgnQtre/m10nGrbVzNsX9FmcCLAAqwmWtCZ1sozjT3rOxVgJD8hn7ro
 J0LEYZuQ0TaCzS2Kaf6+BdXNMWJQShPPyi4UJI490RswzTeg4z2weNIPdlFoyJZd
 Wr7GDPkpHkpFnx65XbBvzOpMNIdJESW9WZLkwy95HfgSkty+3DpmvoKhLyzWOCsF
 AbVJOkjbNgKYJpfu8HmZsV/WB9Ll8aKkMieisY0Y2PHyNv853YkJBuRhLRopx7Ke
 NsGa2jZofuWJxpO0v9FqeVJB1B4iHJ5w2obWixcvGTUJD1Bg30WsQudGVO4tO4SD
 nvt+6vsxYFHr9QaOXIyV
 =WC8K
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180827-v4-pull-request' into staging

ui: misc fixes which piled up during 3.0 release freeze

# gpg: Signature made Mon 27 Aug 2018 09:53:07 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/ui-20180827-v4-pull-request:
  util: promote qemu_egl_rendernode_open() to libqemuutil
  dmabuf: add y0_top, pass it to spice
  ui/vnc: Remove useless parenthesis around DIV_ROUND_UP macro
  ui/sdl2: Fix broken -full-screen CLI option
  spice-display: fix qemu_spice_cursor_refresh_bh locking
  spice-display: access ptr_x/ptr_y under Mutex
  vnc: remove support for deprecated tls, x509, x509verify options
  doc: switch to modern syntax for VNC TLS setup
  sdl2: redraw correctly when scanout_mode enabled.
  ui: use enum to string helpers
  vnc: fix memleak of the "vnc-worker-output" name
  ui/sdl2: Remove the obsolete SDL_INIT_NOPARACHUTE flag

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-08-27 12:30:51 +01:00
commit 025573be71
17 changed files with 143 additions and 241 deletions

View File

@ -1576,6 +1576,7 @@ S: Odd Fixes
F: ui/
F: include/ui/
F: qapi/ui.json
F: util/drm.c
Cocoa graphics
M: Peter Maydell <peter.maydell@linaro.org>

6
include/qemu/drm.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef QEMU_DRM_H_
#define QEMU_DRM_H_
int qemu_drm_rendernode_open(const char *rendernode);
#endif

View File

@ -186,6 +186,7 @@ struct QemuDmaBuf {
uint32_t stride;
uint32_t fourcc;
uint32_t texture;
bool y0_top;
};
typedef struct DisplayChangeListenerOps {

View File

@ -40,26 +40,6 @@ which is the default.
The ``-no-kvm'' argument is now a synonym for setting
``-machine accel=tcg''.
@subsection -vnc tls (since 2.5.0)
The ``-vnc tls'' argument is now a synonym for setting
``-object tls-creds-anon,id=tls0'' combined with
``-vnc tls-creds=tls0'
@subsection -vnc x509 (since 2.5.0)
The ``-vnc x509=/path/to/certs'' argument is now a
synonym for setting
``-object tls-creds-x509,dir=/path/to/certs,id=tls0,verify-peer=no''
combined with ``-vnc tls-creds=tls0'
@subsection -vnc x509verify (since 2.5.0)
The ``-vnc x509verify=/path/to/certs'' argument is now a
synonym for setting
``-object tls-creds-x509,dir=/path/to/certs,id=tls0,verify-peer=yes''
combined with ``-vnc tls-creds=tls0'
@subsection -tftp (since 2.6.0)
The ``-tftp /some/dir'' argument is replaced by either

View File

@ -1103,7 +1103,9 @@ support provides a secure session, but no authentication. This allows any
client to connect, and provides an encrypted session.
@example
qemu-system-i386 [...OPTIONS...] -vnc :1,tls,x509=/etc/pki/qemu -monitor stdio
qemu-system-i386 [...OPTIONS...] \
-object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=no \
-vnc :1,tls-creds=tls0 -monitor stdio
@end example
In the above example @code{/etc/pki/qemu} should contain at least three files,
@ -1118,10 +1120,14 @@ only be readable by the user owning it.
Certificates can also provide a means to authenticate the client connecting.
The server will request that the client provide a certificate, which it will
then validate against the CA certificate. This is a good choice if deploying
in an environment with a private internal certificate authority.
in an environment with a private internal certificate authority. It uses the
same syntax as previously, but with @code{verify-peer} set to @code{yes}
instead.
@example
qemu-system-i386 [...OPTIONS...] -vnc :1,tls,x509verify=/etc/pki/qemu -monitor stdio
qemu-system-i386 [...OPTIONS...] \
-object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=yes \
-vnc :1,tls-creds=tls0 -monitor stdio
@end example
@ -1132,7 +1138,9 @@ Finally, the previous method can be combined with VNC password authentication
to provide two layers of authentication for clients.
@example
qemu-system-i386 [...OPTIONS...] -vnc :1,password,tls,x509verify=/etc/pki/qemu -monitor stdio
qemu-system-i386 [...OPTIONS...] \
-object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=yes \
-vnc :1,tls-creds=tls0,password -monitor stdio
(qemu) change vnc password
Password: ********
(qemu)
@ -1169,7 +1177,9 @@ credentials. This can be enabled, by combining the 'sasl' option
with the aforementioned TLS + x509 options:
@example
qemu-system-i386 [...OPTIONS...] -vnc :1,tls,x509,sasl -monitor stdio
qemu-system-i386 [...OPTIONS...] \
-object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=yes \
-vnc :1,tls-creds=tls0,sasl -monitor stdio
@end example
@node vnc_setup_sasl

View File

@ -84,7 +84,7 @@ static void walk_map(struct xkb_keymap *map, xkb_keycode_t code, void *data)
}
fprintf(outfile, "# evdev %d (0x%x), QKeyCode \"%s\", number 0x%x\n",
evdev, evdev,
QKeyCode_lookup.array[qcode],
QKeyCode_str(qcode),
qcode_to_number(qcode));
/*

View File

@ -1632,49 +1632,6 @@ will cause the VNC server socket to enable the VeNCrypt auth
mechanism. The credentials should have been previously created
using the @option{-object tls-creds} argument.
The @option{tls-creds} parameter obsoletes the @option{tls},
@option{x509}, and @option{x509verify} options, and as such
it is not permitted to set both new and old type options at
the same time.
@item tls
Require that client use TLS when communicating with the VNC server. This
uses anonymous TLS credentials so is susceptible to a man-in-the-middle
attack. It is recommended that this option be combined with either the
@option{x509} or @option{x509verify} options.
This option is now deprecated in favor of using the @option{tls-creds}
argument.
@item x509=@var{/path/to/certificate/dir}
Valid if @option{tls} is specified. Require that x509 credentials are used
for negotiating the TLS session. The server will send its x509 certificate
to the client. It is recommended that a password be set on the VNC server
to provide authentication of the client when this is used. The path following
this option specifies where the x509 certificates are to be loaded from.
See the @ref{vnc_security} section for details on generating certificates.
This option is now deprecated in favour of using the @option{tls-creds}
argument.
@item x509verify=@var{/path/to/certificate/dir}
Valid if @option{tls} is specified. Require that x509 credentials are used
for negotiating the TLS session. The server will send its x509 certificate
to the client, and request that the client send its own x509 certificate.
The server will validate the client's certificate against the CA certificate,
and reject clients when validation fails. If the certificate authority is
trusted, this is a sufficient authentication mechanism. You may still wish
to set a password on the VNC server as a second authentication layer. The
path following this option specifies where the x509 certificates are to
be loaded from. See the @ref{vnc_security} section for details on generating
certificates.
This option is now deprecated in favour of using the @option{tls-creds}
argument.
@item sasl
Require that the client use SASL to authenticate with the VNC server.

View File

@ -2319,7 +2319,7 @@ bool qemu_display_find_default(DisplayOptions *opts)
for (i = 0; i < ARRAY_SIZE(prio); i++) {
if (dpys[prio[i]] == NULL) {
ui_module_load_one(DisplayType_lookup.array[prio[i]]);
ui_module_load_one(DisplayType_str(prio[i]));
}
if (dpys[prio[i]] == NULL) {
continue;
@ -2337,11 +2337,11 @@ void qemu_display_early_init(DisplayOptions *opts)
return;
}
if (dpys[opts->type] == NULL) {
ui_module_load_one(DisplayType_lookup.array[opts->type]);
ui_module_load_one(DisplayType_str(opts->type));
}
if (dpys[opts->type] == NULL) {
error_report("Display '%s' is not available.",
DisplayType_lookup.array[opts->type]);
DisplayType_str(opts->type));
exit(1);
}
if (dpys[opts->type]->early_init) {

View File

@ -15,9 +15,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include <glob.h>
#include <dirent.h>
#include "qemu/drm.h"
#include "qemu/error-report.h"
#include "ui/console.h"
#include "ui/egl-helpers.h"
@ -147,57 +145,12 @@ int qemu_egl_rn_fd;
struct gbm_device *qemu_egl_rn_gbm_dev;
EGLContext qemu_egl_rn_ctx;
static int qemu_egl_rendernode_open(const char *rendernode)
{
DIR *dir;
struct dirent *e;
int r, fd;
char *p;
if (rendernode) {
return open(rendernode, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
}
dir = opendir("/dev/dri");
if (!dir) {
return -1;
}
fd = -1;
while ((e = readdir(dir))) {
if (e->d_type != DT_CHR) {
continue;
}
if (strncmp(e->d_name, "renderD", 7)) {
continue;
}
p = g_strdup_printf("/dev/dri/%s", e->d_name);
r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
if (r < 0) {
g_free(p);
continue;
}
fd = r;
g_free(p);
break;
}
closedir(dir);
if (fd < 0) {
return -1;
}
return fd;
}
int egl_rendernode_init(const char *rendernode, DisplayGLMode mode)
{
qemu_egl_rn_fd = -1;
int rc;
qemu_egl_rn_fd = qemu_egl_rendernode_open(rendernode);
qemu_egl_rn_fd = qemu_drm_rendernode_open(rendernode);
if (qemu_egl_rn_fd == -1) {
error_report("egl: no drm render node available");
goto err;

View File

@ -124,6 +124,11 @@ void sdl2_gl_redraw(struct sdl2_console *scon)
{
assert(scon->opengl);
if (scon->scanout_mode) {
/* sdl2_gl_scanout_flush actually only care about
* the first argument. */
return sdl2_gl_scanout_flush(&scon->dcl, 0, 0, 0, 0);
}
if (scon->surface) {
sdl2_gl_render_surface(scon);
}

View File

@ -761,7 +761,6 @@ static void sdl2_display_early_init(DisplayOptions *o)
static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
{
int flags;
uint8_t data = 0;
char *filename;
int i;
@ -782,8 +781,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
setenv("SDL_VIDEODRIVER", "x11", 0);
#endif
flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
if (SDL_Init(flags)) {
if (SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr, "Could not initialize SDL(%s) - exiting\n",
SDL_GetError());
exit(1);
@ -792,6 +790,8 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
memset(&info, 0, sizeof(info));
SDL_VERSION(&info.version);
gui_fullscreen = o->has_full_screen && o->full_screen;
for (i = 0;; i++) {
QemuConsole *con = qemu_console_lookup_by_index(i);
if (!con) {
@ -844,17 +844,14 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
g_free(filename);
}
if (sdl2_console->opts->has_full_screen &&
sdl2_console->opts->full_screen) {
gui_fullscreen = 1;
gui_grab = 0;
if (gui_fullscreen) {
sdl_grab_start(0);
}
mouse_mode_notifier.notify = sdl_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);
gui_grab = 0;
sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
sdl_cursor_normal = SDL_GetCursor();

View File

@ -450,27 +450,33 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
qemu_mutex_unlock(&ssd->lock);
}
static void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
{
if (ssd->cursor) {
assert(ssd->dcl.con);
dpy_cursor_define(ssd->dcl.con, ssd->cursor);
}
if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
assert(ssd->dcl.con);
dpy_mouse_set(ssd->dcl.con, ssd->mouse_x, ssd->mouse_y, 1);
ssd->mouse_x = -1;
ssd->mouse_y = -1;
}
}
void qemu_spice_cursor_refresh_bh(void *opaque)
{
SimpleSpiceDisplay *ssd = opaque;
qemu_mutex_lock(&ssd->lock);
qemu_spice_cursor_refresh_unlocked(ssd);
qemu_mutex_unlock(&ssd->lock);
if (ssd->cursor) {
QEMUCursor *c = ssd->cursor;
assert(ssd->dcl.con);
cursor_get(c);
qemu_mutex_unlock(&ssd->lock);
dpy_cursor_define(ssd->dcl.con, c);
qemu_mutex_lock(&ssd->lock);
cursor_put(c);
}
if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
int x, y;
assert(ssd->dcl.con);
x = ssd->mouse_x;
y = ssd->mouse_y;
ssd->mouse_x = -1;
ssd->mouse_y = -1;
qemu_mutex_unlock(&ssd->lock);
dpy_mouse_set(ssd->dcl.con, x, y, 1);
} else {
qemu_mutex_unlock(&ssd->lock);
}
}
void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
@ -976,8 +982,10 @@ static void qemu_spice_gl_cursor_position(DisplayChangeListener *dcl,
{
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
qemu_mutex_lock(&ssd->lock);
ssd->ptr_x = pos_x;
ssd->ptr_y = pos_y;
qemu_mutex_unlock(&ssd->lock);
}
static void qemu_spice_gl_release_dmabuf(DisplayChangeListener *dcl,
@ -1048,17 +1056,23 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
/* note: spice server will close the fd, so hand over a dup */
spice_qxl_gl_scanout(&ssd->qxl, dup(dmabuf->fd),
dmabuf->width, dmabuf->height,
dmabuf->stride, dmabuf->fourcc, false);
dmabuf->stride, dmabuf->fourcc,
dmabuf->y0_top);
}
qemu_spice_gl_monitor_config(ssd, 0, 0, dmabuf->width, dmabuf->height);
ssd->guest_dmabuf_refresh = false;
}
if (render_cursor) {
int x, y;
qemu_mutex_lock(&ssd->lock);
x = ssd->ptr_x;
y = ssd->ptr_y;
qemu_mutex_unlock(&ssd->lock);
egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb,
!y_0_top);
egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb,
!y_0_top, ssd->ptr_x, ssd->ptr_y);
!y_0_top, x, y);
glFlush();
}

View File

@ -979,7 +979,7 @@ static int send_mono_rect(VncState *vs, int x, int y,
}
#endif
bytes = (DIV_ROUND_UP(w, 8)) * h;
bytes = DIV_ROUND_UP(w, 8) * h;
vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);

View File

@ -193,6 +193,7 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
static void vnc_async_encoding_end(VncState *orig, VncState *local)
{
buffer_free(&local->output);
orig->tight = local->tight;
orig->zlib = local->zlib;
orig->hextile = local->hextile;
@ -278,7 +279,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
/* Copy persistent encoding data */
vnc_async_encoding_end(job->vs, &vs);
qemu_bh_schedule(job->vs->bh);
qemu_bh_schedule(job->vs->bh);
} else {
buffer_reset(&vs.output);
/* Copy persistent encoding data */

View File

@ -2967,7 +2967,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb));
guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
guest_stride = pixman_image_get_stride(vd->guest.fb);
guest_ll = pixman_image_get_width(vd->guest.fb) * (DIV_ROUND_UP(guest_bpp, 8));
guest_ll = pixman_image_get_width(vd->guest.fb)
* DIV_ROUND_UP(guest_bpp, 8);
}
line_bytes = MIN(server_stride, guest_ll);
@ -3344,10 +3345,6 @@ static QemuOptsList qemu_vnc_opts = {
},{
.name = "tls-creds",
.type = QEMU_OPT_STRING,
},{
/* Deprecated in favour of tls-creds */
.name = "x509",
.type = QEMU_OPT_STRING,
},{
.name = "share",
.type = QEMU_OPT_STRING,
@ -3384,14 +3381,6 @@ static QemuOptsList qemu_vnc_opts = {
},{
.name = "sasl",
.type = QEMU_OPT_BOOL,
},{
/* Deprecated in favour of tls-creds */
.name = "tls",
.type = QEMU_OPT_BOOL,
},{
/* Deprecated in favour of tls-creds */
.name = "x509verify",
.type = QEMU_OPT_STRING,
},{
.name = "acl",
.type = QEMU_OPT_BOOL,
@ -3519,51 +3508,6 @@ vnc_display_setup_auth(int *auth,
}
/*
* Handle back compat with old CLI syntax by creating some
* suitable QCryptoTLSCreds objects
*/
static QCryptoTLSCreds *
vnc_display_create_creds(bool x509,
bool x509verify,
const char *dir,
const char *id,
Error **errp)
{
gchar *credsid = g_strdup_printf("tlsvnc%s", id);
Object *parent = object_get_objects_root();
Object *creds;
Error *err = NULL;
if (x509) {
creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_X509,
parent,
credsid,
&err,
"endpoint", "server",
"dir", dir,
"verify-peer", x509verify ? "yes" : "no",
NULL);
} else {
creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_ANON,
parent,
credsid,
&err,
"endpoint", "server",
NULL);
}
g_free(credsid);
if (err) {
error_propagate(errp, err);
return NULL;
}
return QCRYPTO_TLS_CREDS(creds);
}
static int vnc_display_get_address(const char *addrstr,
bool websocket,
bool reverse,
@ -3930,15 +3874,6 @@ void vnc_display_open(const char *id, Error **errp)
credid = qemu_opt_get(opts, "tls-creds");
if (credid) {
Object *creds;
if (qemu_opt_get(opts, "tls") ||
qemu_opt_get(opts, "x509") ||
qemu_opt_get(opts, "x509verify")) {
error_setg(errp,
"'tls-creds' parameter is mutually exclusive with "
"'tls', 'x509' and 'x509verify' parameters");
goto fail;
}
creds = object_resolve_path_component(
object_get_objects_root(), credid);
if (!creds) {
@ -3961,31 +3896,6 @@ void vnc_display_open(const char *id, Error **errp)
"Expecting TLS credentials with a server endpoint");
goto fail;
}
} else {
const char *path;
bool tls = false, x509 = false, x509verify = false;
tls = qemu_opt_get_bool(opts, "tls", false);
if (tls) {
path = qemu_opt_get(opts, "x509");
if (path) {
x509 = true;
} else {
path = qemu_opt_get(opts, "x509verify");
if (path) {
x509 = true;
x509verify = true;
}
}
vd->tlscreds = vnc_display_create_creds(x509,
x509verify,
path,
vd->id,
errp);
if (!vd->tlscreds) {
goto fail;
}
}
}
acl = qemu_opt_get_bool(opts, "acl", false);

View File

@ -50,3 +50,4 @@ util-obj-y += stats64.o
util-obj-y += systemd.o
util-obj-y += iova-tree.o
util-obj-$(CONFIG_LINUX) += vfio-helpers.o
util-obj-$(CONFIG_OPENGL) += drm.o

66
util/drm.c Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2015-2016 Gerd Hoffmann <kraxel@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu/drm.h"
#include <glob.h>
#include <dirent.h>
int qemu_drm_rendernode_open(const char *rendernode)
{
DIR *dir;
struct dirent *e;
int r, fd;
char *p;
if (rendernode) {
return open(rendernode, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
}
dir = opendir("/dev/dri");
if (!dir) {
return -1;
}
fd = -1;
while ((e = readdir(dir))) {
if (e->d_type != DT_CHR) {
continue;
}
if (strncmp(e->d_name, "renderD", 7)) {
continue;
}
p = g_strdup_printf("/dev/dri/%s", e->d_name);
r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
if (r < 0) {
g_free(p);
continue;
}
fd = r;
g_free(p);
break;
}
closedir(dir);
if (fd < 0) {
return -1;
}
return fd;
}