void QXcbConnection::initializeDri2() { xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection, m_screens[0]->root(), XCB_DRI2_DRIVER_TYPE_DRI); xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection, connect_cookie, NULL); if (! connect || connect->driver_name_length + connect->device_name_length == 0) { qDebug() << "Failed to connect to dri2"; return; } m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect), xcb_dri2_connect_device_name_length (connect)); delete connect; int fd = open(m_dri2_device_name.constData(), O_RDWR); if (fd < 0) { qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName"; m_dri2_device_name = QByteArray(); return; } drm_magic_t magic; if (drmGetMagic(fd, &magic)) { qDebug() << "Failed to get drmMagic"; return; } xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection, m_screens[0]->root(), magic); xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection, authenticate_cookie, NULL); if (authenticate == NULL || !authenticate->authenticated) { fprintf(stderr, "DRI2: failed to authenticate\n"); free(authenticate); return; } delete authenticate; EGLDisplay display = eglGetDRMDisplayMESA(fd); if (!display) { fprintf(stderr, "failed to create display\n"); return; } m_egl_display = display; EGLint major,minor; if (!eglInitialize(display, &major, &minor)) { fprintf(stderr, "failed to initialize display\n"); return; } }
static void pipe_loader_drm_x_auth(int fd) { #ifdef HAVE_PIPE_LOADER_XCB /* Try authenticate with the X server to give us access to devices that X * is running on. */ xcb_connection_t *xcb_conn; const xcb_setup_t *xcb_setup; xcb_screen_iterator_t s; xcb_dri2_connect_cookie_t connect_cookie; xcb_dri2_connect_reply_t *connect; drm_magic_t magic; xcb_dri2_authenticate_cookie_t authenticate_cookie; xcb_dri2_authenticate_reply_t *authenticate; int screen; xcb_conn = xcb_connect(NULL, &screen); if(!xcb_conn) return; xcb_setup = xcb_get_setup(xcb_conn); if (!xcb_setup) goto disconnect; s = xcb_setup_roots_iterator(xcb_setup); connect_cookie = xcb_dri2_connect_unchecked(xcb_conn, get_xcb_screen(s, screen)->root, XCB_DRI2_DRIVER_TYPE_DRI); connect = xcb_dri2_connect_reply(xcb_conn, connect_cookie, NULL); if (!connect || connect->driver_name_length + connect->device_name_length == 0) { goto disconnect; } if (drmGetMagic(fd, &magic)) goto disconnect; authenticate_cookie = xcb_dri2_authenticate_unchecked(xcb_conn, s.data->root, magic); authenticate = xcb_dri2_authenticate_reply(xcb_conn, authenticate_cookie, NULL); FREE(authenticate); disconnect: xcb_disconnect(xcb_conn); #endif }
static EGLBoolean dri2_connect(struct dri2_egl_display *dri2_dpy) { xcb_xfixes_query_version_reply_t *xfixes_query; xcb_xfixes_query_version_cookie_t xfixes_query_cookie; xcb_dri2_query_version_reply_t *dri2_query; xcb_dri2_query_version_cookie_t dri2_query_cookie; xcb_dri2_connect_reply_t *connect; xcb_dri2_connect_cookie_t connect_cookie; xcb_generic_error_t *error; xcb_screen_iterator_t s; char *driver_name, *device_name; const xcb_query_extension_reply_t *extension; xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id); if (!(extension && extension->present)) return EGL_FALSE; extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id); if (!(extension && extension->present)) return EGL_FALSE; xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION); s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn, s.data->root, XCB_DRI2_DRIVER_TYPE_DRI); xfixes_query = xcb_xfixes_query_version_reply (dri2_dpy->conn, xfixes_query_cookie, &error); if (xfixes_query == NULL || error != NULL || xfixes_query->major_version < 2) { _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version"); free(error); return EGL_FALSE; } free(xfixes_query); dri2_query = xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); if (dri2_query == NULL || error != NULL) { _eglLog(_EGL_WARNING, "DRI2: failed to query version"); free(error); return EGL_FALSE; } dri2_dpy->dri2_major = dri2_query->major_version; dri2_dpy->dri2_minor = dri2_query->minor_version; free(dri2_query); connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0) { _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); return EGL_FALSE; } driver_name = xcb_dri2_connect_driver_name (connect); dri2_dpy->driver_name = dri2_strndup(driver_name, xcb_dri2_connect_driver_name_length (connect)); device_name = xcb_dri2_connect_device_name (connect); dri2_dpy->device_name = dri2_strndup(device_name, xcb_dri2_connect_device_name_length (connect)); if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { free(dri2_dpy->device_name); free(dri2_dpy->driver_name); free(connect); return EGL_FALSE; } free(connect); return EGL_TRUE; }
static EGLBoolean dri2_x11_connect(struct dri2_egl_display *dri2_dpy) { xcb_xfixes_query_version_reply_t *xfixes_query; xcb_xfixes_query_version_cookie_t xfixes_query_cookie; xcb_dri2_query_version_reply_t *dri2_query; xcb_dri2_query_version_cookie_t dri2_query_cookie; xcb_dri2_connect_reply_t *connect; xcb_dri2_connect_cookie_t connect_cookie; xcb_generic_error_t *error; xcb_screen_iterator_t s; xcb_screen_t *screen; char *driver_name, *loader_driver_name, *device_name; const xcb_query_extension_reply_t *extension; xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id); if (!(extension && extension->present)) return EGL_FALSE; extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id); if (!(extension && extension->present)) return EGL_FALSE; xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION); s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); screen = get_xcb_screen(s, dri2_dpy->screen); if (!screen) { _eglLog(_EGL_WARNING, "DRI2: failed to get xcb screen"); return EGL_FALSE; } connect_cookie = xcb_dri2_connect_unchecked(dri2_dpy->conn, screen->root, XCB_DRI2_DRIVER_TYPE_DRI); xfixes_query = xcb_xfixes_query_version_reply (dri2_dpy->conn, xfixes_query_cookie, &error); if (xfixes_query == NULL || error != NULL || xfixes_query->major_version < 2) { _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version"); free(error); return EGL_FALSE; } free(xfixes_query); dri2_query = xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); if (dri2_query == NULL || error != NULL) { _eglLog(_EGL_WARNING, "DRI2: failed to query version"); free(error); return EGL_FALSE; } dri2_dpy->dri2_major = dri2_query->major_version; dri2_dpy->dri2_minor = dri2_query->minor_version; free(dri2_query); connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0) { _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); return EGL_FALSE; } device_name = xcb_dri2_connect_device_name (connect); dri2_dpy->device_name = strndup(device_name, xcb_dri2_connect_device_name_length(connect)); dri2_dpy->fd = loader_open_device(dri2_dpy->device_name); if (dri2_dpy->fd == -1) { _eglLog(_EGL_WARNING, "DRI2: could not open %s (%s)", dri2_dpy->device_name, strerror(errno)); free(dri2_dpy->device_name); free(connect); return EGL_FALSE; } if (!dri2_x11_local_authenticate(dri2_dpy)) { close(dri2_dpy->fd); free(dri2_dpy->device_name); free(connect); return EGL_FALSE; } driver_name = xcb_dri2_connect_driver_name (connect); /* If Mesa knows about the appropriate driver for this fd, then trust it. * Otherwise, default to the server's value. */ loader_driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0); if (loader_driver_name) { dri2_dpy->driver_name = loader_driver_name; } else { dri2_dpy->driver_name = strndup(driver_name, xcb_dri2_connect_driver_name_length(connect)); } if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { close(dri2_dpy->fd); free(dri2_dpy->device_name); free(dri2_dpy->driver_name); free(connect); return EGL_FALSE; } free(connect); return EGL_TRUE; }
static int dri2_connect(Display *display) { xcb_dri2_query_version_cookie_t query_version_cookie; xcb_dri2_query_version_reply_t *query_version_reply; xcb_dri2_connect_cookie_t connect_cookie; xcb_dri2_connect_reply_t *connect_reply; xcb_dri2_authenticate_cookie_t auth_cookie; xcb_dri2_authenticate_reply_t *auth_reply; xcb_screen_t *root; xcb_connection_t *c = XGetXCBConnection(display); drm_magic_t magic; const xcb_query_extension_reply_t *dri2_reply; char *device_name; int len; root = xcb_aux_get_screen(c, DefaultScreen(display)); dri2_reply = xcb_get_extension_data(c, &xcb_dri2_id); if (!dri2_reply) { XVMC_ERR("DRI2 required"); return BadValue; } /* Query the extension and make our first use of it at the same time. */ query_version_cookie = xcb_dri2_query_version(c, 1, 0); connect_cookie = xcb_dri2_connect(c, root->root, DRI2DriverDRI); query_version_reply = xcb_dri2_query_version_reply(c, query_version_cookie, NULL); connect_reply = xcb_dri2_connect_reply(c, connect_cookie, NULL); if (!query_version_reply) { XVMC_ERR("DRI2 required"); return BadValue; } free(query_version_reply); len = xcb_dri2_connect_device_name_length(connect_reply); device_name = malloc(len + 1); if (!device_name) { XVMC_ERR("malloc failure"); return BadAlloc; } strncpy(device_name, xcb_dri2_connect_device_name(connect_reply), len); device_name[len] = 0; xvmc_driver->fd = open(device_name, O_RDWR); free(device_name); free(connect_reply); if (xvmc_driver->fd < 0) { XVMC_ERR("Failed to open drm device: %s\n", strerror(errno)); return BadValue; } if (drmGetMagic(xvmc_driver->fd, &magic)) { XVMC_ERR("Failed to get magic\n"); return BadValue; } auth_cookie = xcb_dri2_authenticate(c, root->root, magic); auth_reply = xcb_dri2_authenticate_reply(c, auth_cookie, NULL); if (!auth_reply) { XVMC_ERR("Failed to authenticate magic %d\n", magic); return BadValue; } free(auth_reply); return Success; }
struct vl_screen * vl_dri2_screen_create(Display *display, int screen) { struct vl_dri_screen *scrn; const xcb_query_extension_reply_t *extension; xcb_dri2_query_version_cookie_t dri2_query_cookie; xcb_dri2_query_version_reply_t *dri2_query = NULL; xcb_dri2_connect_cookie_t connect_cookie; xcb_dri2_connect_reply_t *connect = NULL; xcb_dri2_authenticate_cookie_t authenticate_cookie; xcb_dri2_authenticate_reply_t *authenticate = NULL; xcb_screen_iterator_t s; xcb_generic_error_t *error = NULL; char *device_name; int fd, device_name_length; unsigned driverType; drm_magic_t magic; assert(display); scrn = CALLOC_STRUCT(vl_dri_screen); if (!scrn) return NULL; scrn->conn = XGetXCBConnection(display); if (!scrn->conn) goto free_screen; xcb_prefetch_extension_data(scrn->conn, &xcb_dri2_id); extension = xcb_get_extension_data(scrn->conn, &xcb_dri2_id); if (!(extension && extension->present)) goto free_screen; dri2_query_cookie = xcb_dri2_query_version (scrn->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION); dri2_query = xcb_dri2_query_version_reply (scrn->conn, dri2_query_cookie, &error); if (dri2_query == NULL || error != NULL || dri2_query->minor_version < 2) goto free_query; s = xcb_setup_roots_iterator(xcb_get_setup(scrn->conn)); scrn->base.xcb_screen = get_xcb_screen(s, screen); if (!scrn->base.xcb_screen) goto free_query; driverType = XCB_DRI2_DRIVER_TYPE_DRI; { char *prime = getenv("DRI_PRIME"); if (prime) { unsigned primeid; errno = 0; primeid = strtoul(prime, NULL, 0); if (errno == 0) driverType |= ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift); } } connect_cookie = xcb_dri2_connect_unchecked( scrn->conn, ((xcb_screen_t *)(scrn->base.xcb_screen))->root, driverType); connect = xcb_dri2_connect_reply(scrn->conn, connect_cookie, NULL); if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0) goto free_connect; device_name_length = xcb_dri2_connect_device_name_length(connect); device_name = CALLOC(1, device_name_length + 1); if (!device_name) goto free_connect; memcpy(device_name, xcb_dri2_connect_device_name(connect), device_name_length); fd = loader_open_device(device_name); free(device_name); if (fd < 0) goto free_connect; if (drmGetMagic(fd, &magic)) goto close_fd; authenticate_cookie = xcb_dri2_authenticate_unchecked( scrn->conn, ((xcb_screen_t *)(scrn->base.xcb_screen))->root, magic); authenticate = xcb_dri2_authenticate_reply(scrn->conn, authenticate_cookie, NULL); if (authenticate == NULL || !authenticate->authenticated) goto free_authenticate; if (pipe_loader_drm_probe_fd(&scrn->base.dev, fd)) scrn->base.pscreen = pipe_loader_create_screen(scrn->base.dev); if (!scrn->base.pscreen) goto release_pipe; scrn->base.destroy = vl_dri2_screen_destroy; scrn->base.texture_from_drawable = vl_dri2_screen_texture_from_drawable; scrn->base.get_dirty_area = vl_dri2_screen_get_dirty_area; scrn->base.get_timestamp = vl_dri2_screen_get_timestamp; scrn->base.set_next_timestamp = vl_dri2_screen_set_next_timestamp; scrn->base.get_private = vl_dri2_screen_get_private; scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer; vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); /* The pipe loader duplicates the fd */ close(fd); free(authenticate); free(connect); free(dri2_query); free(error); return &scrn->base; release_pipe: if (scrn->base.dev) pipe_loader_release(&scrn->base.dev, 1); free_authenticate: free(authenticate); close_fd: close(fd); free_connect: free(connect); free_query: free(dri2_query); free(error); free_screen: FREE(scrn); return NULL; }