int mggh::DRMHelper::get_authenticated_fd() { /* We must have our own device fd first, so that it has become the DRM master */ if (fd < 0) BOOST_THROW_EXCEPTION( std::runtime_error( "Tried to get authenticated DRM fd before setting up the DRM master")); int auth_fd = open_drm_device(); if (auth_fd < 0) BOOST_THROW_EXCEPTION( std::runtime_error("Failed to open DRM device for authenticated fd")); drm_magic_t magic; int ret = -1; if ((ret = drmGetMagic(auth_fd, &magic)) < 0) { close(auth_fd); BOOST_THROW_EXCEPTION( boost::enable_error_info( std::runtime_error("Failed to get DRM device magic cookie")) << boost::errinfo_errno(ret)); } if ((ret = drmAuthMagic(fd, magic)) < 0) { close(auth_fd); BOOST_THROW_EXCEPTION( boost::enable_error_info( std::runtime_error("Failed to authenticate DRM device magic cookie")) << boost::errinfo_errno(ret)); } return auth_fd; }
static void xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device) { struct xwl_screen *xwl_screen = data; drm_magic_t magic; xwl_screen->device_name = strdup(device); if (!xwl_screen->device_name) return; xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC); if (xwl_screen->drm_fd == -1) { ErrorF("wayland-egl: could not open %s (%s)\n", xwl_screen->device_name, strerror(errno)); return; } if (is_fd_render_node(xwl_screen->drm_fd)) { xwl_screen->fd_render_node = 1; xwl_drm_init_egl(xwl_screen); } else { drmGetMagic(xwl_screen->drm_fd, &magic); wl_drm_authenticate(xwl_screen->drm, magic); } }
static void drm_handle_device(void *data, struct wl_drm *drm, const char *device) { VADisplayContextP const pDisplayContext = data; VADriverContextP const ctx = pDisplayContext->pDriverContext; VADisplayContextWaylandDRM * const wl_drm_ctx = pDisplayContext->opaque; struct drm_state * const drm_state = ctx->drm_state; drm_magic_t magic; struct stat st; if (stat(device, &st) < 0) { va_wayland_error("failed to identify %s: %s (errno %d)", device, strerror(errno), errno); return; } if (!S_ISCHR(st.st_mode)) { va_wayland_error("%s is not a device", device); return; } drm_state->fd = open(device, O_RDWR); if (drm_state->fd < 0) { va_wayland_error("failed to open %s: %s (errno %d)", device, strerror(errno), errno); return; } drmGetMagic(drm_state->fd, &magic); wl_drm_authenticate(wl_drm_ctx->drm, magic); }
static inline int is_drm_master(int drm_fd) { drm_magic_t magic; return drmGetMagic(drm_fd, &magic) == 0 && drmAuthMagic(drm_fd, magic) == 0; }
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 int init_drm(struct display *d) { EGLint major, minor; int fd; drm_magic_t magic; fd = open(d->device_name, O_RDWR); if (fd < 0) { fprintf(stderr, "drm open failed: %m\n"); return -1; } if (drmGetMagic(fd, &magic)) { fprintf(stderr, "DRI2: failed to get drm magic"); return -1; } /* Wait for authenticated event */ wl_drm_authenticate(d->drm, magic); wl_display_iterate(d->display, WL_DISPLAY_WRITABLE); while (!d->authenticated) wl_display_iterate(d->display, WL_DISPLAY_READABLE); d->dpy = eglGetDRMDisplayMESA(fd); if (!eglInitialize(d->dpy, &major, &minor)) { fprintf(stderr, "failed to initialize display\n"); return -1; } if (!eglBindAPI(EGL_OPENGL_API)) { fprintf(stderr, "failed to bind api EGL_OPENGL_API\n"); return -1; } d->ctx = eglCreateContext(d->dpy, NULL, EGL_NO_CONTEXT, NULL); if (d->ctx == NULL) { fprintf(stderr, "failed to create context\n"); return -1; } if (!eglMakeCurrent(d->dpy, NULL, NULL, d->ctx)) { fprintf(stderr, "faile to make context current\n"); return -1; } #ifdef HAVE_CAIRO_EGL d->device = cairo_egl_device_create(d->dpy, d->ctx); if (d->device == NULL) { fprintf(stderr, "failed to get cairo drm device\n"); return -1; } #endif return 0; }
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 int dri2_connect(Display *dpy, char **driver) { int eventBase, errorBase, major, minor; char *device; drm_magic_t magic; Window root; int fd; if (!DRI2InitDisplay(dpy, &ops)) { ERROR_MSG("DRI2InitDisplay failed"); return -1; } if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) { ERROR_MSG("DRI2QueryExtension failed"); return -1; } MSG("DRI2QueryExtension: eventBase=%d, errorBase=%d", eventBase, errorBase); if (!DRI2QueryVersion(dpy, &major, &minor)) { ERROR_MSG("DRI2QueryVersion failed"); return -1; } MSG("DRI2QueryVersion: major=%d, minor=%d", major, minor); root = RootWindow(dpy, DefaultScreen(dpy)); if (!DRI2Connect(dpy, root, driver, &device)) { ERROR_MSG("DRI2Connect failed"); return -1; } MSG("DRI2Connect: driver=%s, device=%s", *driver, device); fd = open(device, O_RDWR); if (fd < 0) { ERROR_MSG("open failed"); return fd; } if (drmGetMagic(fd, &magic)) { ERROR_MSG("drmGetMagic failed"); return -1; } if (!DRI2Authenticate(dpy, root, magic)) { ERROR_MSG("DRI2Authenticate failed"); return -1; } return fd; }
/** * Enable DRI2 and returns the file descriptor of the DRM device. The file * descriptor will be closed automatically when the screen is destoryed. */ int x11_screen_enable_dri2(struct x11_screen *xscr, x11_drawable_invalidate_buffers invalidate_buffers, void *user_data) { if (xscr->dri_fd < 0) { int fd; drm_magic_t magic; /* get the driver name and the device name first */ if (!x11_screen_probe_dri2(xscr, NULL, NULL)) return -1; fd = open(xscr->dri_device, O_RDWR); if (fd < 0) { _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device); return -1; } memset(&magic, 0, sizeof(magic)); if (drmGetMagic(fd, &magic)) { _eglLog(_EGL_WARNING, "failed to get magic"); close(fd); return -1; } if (!DRI2Authenticate(xscr->dpy, RootWindow(xscr->dpy, xscr->number), magic)) { _eglLog(_EGL_WARNING, "failed to authenticate magic"); close(fd); return -1; } if (!x11_screen_init_glx(xscr)) { _eglLog(_EGL_WARNING, "failed to initialize GLX"); close(fd); return -1; } if (xscr->glx_dpy->xscr) { _eglLog(_EGL_WARNING, "display is already managed by another x11 screen"); close(fd); return -1; } xscr->glx_dpy->xscr = xscr; xscr->dri_invalidate_buffers = invalidate_buffers; xscr->dri_user_data = user_data; xscr->dri_fd = fd; } return xscr->dri_fd; }
static EGLBoolean dri2_x11_local_authenticate(struct dri2_egl_display *dri2_dpy) { #ifdef HAVE_LIBDRM drm_magic_t magic; if (drmGetMagic(dri2_dpy->fd, &magic)) { _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic"); return EGL_FALSE; } if (dri2_x11_do_authenticate(dri2_dpy, magic) < 0) { _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); return EGL_FALSE; } #endif return EGL_TRUE; }
static EGLBoolean dri2_authenticate(_EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); drm_magic_t magic; if (drmGetMagic(dri2_dpy->fd, &magic)) { _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic"); return EGL_FALSE; } if (dri2_x11_authenticate(disp, magic) < 0) { _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); return EGL_FALSE; } return EGL_TRUE; }
static int xwl_dri3_open_client(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *pfd) { struct xwl_screen *xwl_screen = xwl_screen_get(screen); struct xwl_auth_state *state; struct wl_callback *callback; drm_magic_t magic; int fd; fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC); if (fd < 0) return BadAlloc; if (xwl_screen->fd_render_node) { *pfd = fd; return Success; } state = malloc(sizeof *state); if (state == NULL) { close(fd); return BadAlloc; } state->client = client; state->fd = fd; if (drmGetMagic(state->fd, &magic) < 0) { close(state->fd); free(state); return BadMatch; } wl_drm_authenticate(xwl_screen->drm, magic); callback = wl_display_sync(xwl_screen->display); wl_callback_add_listener(callback, &sync_listener, state); IgnoreClient(client); return Success; }
static void drm_handle_device(void *data, struct wl_drm *drm, const char *device) { struct wayland_drm_display *drmdpy = data; drm_magic_t magic; drmdpy->device_name = strdup(device); if (!drmdpy->device_name) return; drmdpy->fd = open(drmdpy->device_name, O_RDWR); if (drmdpy->fd == -1) { _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)", drmdpy->device_name, strerror(errno)); return; } drmGetMagic(drmdpy->fd, &magic); wl_drm_authenticate(drmdpy->wl_drm, magic); }
Bool isDRI2Connected(VADriverContextP ctx, char **driver_name) { struct dri_state *dri_state = (struct dri_state *)ctx->drm_state; int major, minor; int error_base; int event_base; char *device_name = NULL; drm_magic_t magic; *driver_name = NULL; dri_state->base.fd = -1; dri_state->base.auth_type = VA_NONE; if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base)) goto err_out; if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor)) goto err_out; if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen), driver_name, &device_name) || !device_name) goto err_out; dri_state->base.fd = open(device_name, O_RDWR); assert(dri_state->base.fd >= 0); if (dri_state->base.fd < 0) goto err_out; if (drmGetMagic(dri_state->base.fd, &magic)) goto err_out; if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen), magic)) goto err_out; dri_state->base.auth_type = VA_DRI2; dri_state->createDrawable = dri2CreateDrawable; dri_state->destroyDrawable = dri2DestroyDrawable; dri_state->swapBuffer = dri2SwapBuffer; dri_state->getRenderingBuffer = dri2GetRenderingBuffer; dri_state->close = dri2Close; gsDRI2SwapAvailable = (minor >= 2); Xfree(device_name); return True; err_out: if (device_name) Xfree(device_name); if (*driver_name) Xfree(*driver_name); if (dri_state->base.fd >= 0) close(dri_state->base.fd); *driver_name = NULL; dri_state->base.fd = -1; return False; }
static struct pipe_screen * radeon_hardpipe_screen_create(void) { Display *dpy; Window rootWin; XWindowAttributes winAttr; int isCapable; int screen; char *driverName; char *curBusID; unsigned magic; int ddxDriverMajor; int ddxDriverMinor; int ddxDriverPatch; drm_handle_t sAreaOffset; int ret; int drmFD; drm_context_t hHWContext; XID id; dpy = XOpenDisplay(":0"); if (!dpy) { fprintf(stderr, "Open Display Failed\n"); return NULL; } screen = DefaultScreen(dpy); rootWin = RootWindow(dpy, screen); XGetWindowAttributes(dpy, rootWin, &winAttr); ret = uniDRIQueryDirectRenderingCapable(dpy, screen, &isCapable); if (!ret || !isCapable) { fprintf(stderr, "No DRI on this display:sceen\n"); goto error; } if (!uniDRIOpenConnection(dpy, screen, &sAreaOffset, &curBusID)) { fprintf(stderr, "Could not open DRI connection.\n"); goto error; } if (!uniDRIGetClientDriverName(dpy, screen, &ddxDriverMajor, &ddxDriverMinor, &ddxDriverPatch, &driverName)) { fprintf(stderr, "Could not get DRI driver name.\n"); goto error; } if ((drmFD = drmOpen(NULL, curBusID)) < 0) { perror("DRM Device could not be opened"); goto error; } drmGetMagic(drmFD, &magic); if (!uniDRIAuthConnection(dpy, screen, magic)) { fprintf(stderr, "Could not get X server to authenticate us.\n"); goto error; } if (!uniDRICreateContext(dpy, screen, winAttr.visual, &id, &hHWContext)) { fprintf(stderr, "Could not create DRI context.\n"); goto error; } /* FIXME: create a radeon pipe_screen from drmFD and hHWContext */ return NULL; error: return NULL; }
/* * Get the magic for authentication. */ int gralloc_drm_get_magic(struct gralloc_drm_t *drm, int32_t *magic) { return drmGetMagic(drm->fd, (drm_magic_t *) magic); }
Bool isDRI1Connected(VADriverContextP ctx, char **driver_name) { struct dri_state *dri_state = (struct dri_state *)ctx->drm_state; int direct_capable; int driver_major; int driver_minor; int driver_patch; int newlyopened; char *BusID; drm_magic_t magic; *driver_name = NULL; dri_state->base.fd = -1; dri_state->pSAREA = MAP_FAILED; dri_state->base.auth_type = VA_NONE; if (!VA_DRIQueryDirectRenderingCapable(ctx->native_dpy, ctx->x11_screen, &direct_capable)) goto err_out0; if (!direct_capable) goto err_out0; if (!VA_DRIGetClientDriverName(ctx->native_dpy, ctx->x11_screen, &driver_major, &driver_minor, &driver_patch, driver_name)) goto err_out0; if (!VA_DRIOpenConnection(ctx->native_dpy, ctx->x11_screen, &dri_state->hSAREA, &BusID)) goto err_out0; dri_state->base.fd = drmOpenOnce(NULL, BusID, &newlyopened); XFree(BusID); if (dri_state->base.fd < 0) goto err_out1; if (drmGetMagic(dri_state->base.fd, &magic)) goto err_out1; if (newlyopened && !VA_DRIAuthConnection(ctx->native_dpy, ctx->x11_screen, magic)) goto err_out1; if (drmMap(dri_state->base.fd, dri_state->hSAREA, SAREA_MAX, &dri_state->pSAREA)) goto err_out1; if (!VA_DRICreateContext(ctx->native_dpy, ctx->x11_screen, DefaultVisual(ctx->native_dpy, ctx->x11_screen), &dri_state->hwContextID, &dri_state->hwContext)) goto err_out1; dri_state->base.auth_type = VA_DRI1; dri_state->createDrawable = dri1CreateDrawable; dri_state->destroyDrawable = dri1DestroyDrawable; dri_state->swapBuffer = dri1SwapBuffer; dri_state->getRenderingBuffer = dri1GetRenderingBuffer; dri_state->close = dri1Close; return True; err_out1: if (dri_state->pSAREA != MAP_FAILED) drmUnmap(dri_state->pSAREA, SAREA_MAX); if (dri_state->base.fd >= 0) drmCloseOnce(dri_state->base.fd); VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen); err_out0: if (*driver_name) XFree(*driver_name); dri_state->pSAREA = MAP_FAILED; dri_state->base.fd = -1; *driver_name = NULL; return False; }
static __GLXDRIscreen * dri2CreateScreen(__GLXscreenConfigs * psc, int screen, __GLXdisplayPrivate * priv) { const __DRIconfig **driver_configs; const __DRIextension **extensions; const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) priv->dri2Display; __GLXDRIscreen *psp; char *driverName, *deviceName; drm_magic_t magic; int i; psp = Xmalloc(sizeof *psp); if (psp == NULL) return NULL; if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), &driverName, &deviceName)) { XFree(psp); return NULL; } psc->driver = driOpenDriver(driverName); if (psc->driver == NULL) { ErrorMessageF("driver pointer missing\n"); goto handle_error; } extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); if (extensions == NULL) { ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); goto handle_error; } for (i = 0; extensions[i]; i++) { if (strcmp(extensions[i]->name, __DRI_CORE) == 0) psc->core = (__DRIcoreExtension *) extensions[i]; if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) psc->dri2 = (__DRIdri2Extension *) extensions[i]; } if (psc->core == NULL || psc->dri2 == NULL) { ErrorMessageF("core dri or dri2 extension not found\n"); goto handle_error; } psc->fd = open(deviceName, O_RDWR); if (psc->fd < 0) { ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); goto handle_error; } if (drmGetMagic(psc->fd, &magic)) { ErrorMessageF("failed to get magic\n"); goto handle_error; } if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { ErrorMessageF("failed to authenticate magic %d\n", magic); goto handle_error; } /* If the server does not support the protocol for * DRI2GetBuffersWithFormat, don't supply that interface to the driver. */ psc->__driScreen = psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1) ? loader_extensions_old : loader_extensions), &driver_configs, psc); if (psc->__driScreen == NULL) { ErrorMessageF("failed to create dri screen\n"); goto handle_error; } driBindCommonExtensions(psc); dri2BindExtensions(psc); psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); psc->driver_configs = driver_configs; psp->destroyScreen = dri2DestroyScreen; psp->createContext = dri2CreateContext; psp->createDrawable = dri2CreateDrawable; psp->swapBuffers = dri2SwapBuffers; psp->waitGL = dri2WaitGL; psp->waitX = dri2WaitX; psp->getDrawableMSC = NULL; psp->waitForMSC = NULL; psp->waitForSBC = NULL; psp->setSwapInterval = NULL; psp->getSwapInterval = NULL; if (pdp->driMinor >= 2) { #ifdef X_DRI2GetMSC psp->getDrawableMSC = dri2DrawableGetMSC; #endif #ifdef X_DRI2WaitMSC psp->waitForMSC = dri2WaitForMSC; psp->waitForSBC = dri2WaitForSBC; #endif #ifdef X_DRI2SwapInterval psp->setSwapInterval = dri2SetSwapInterval; psp->getSwapInterval = dri2GetSwapInterval; #endif #if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) __glXEnableDirectExtension(psc, "GLX_OML_sync_control"); #endif } /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always * available.*/ psp->copySubBuffer = dri2CopySubBuffer; __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); Xfree(driverName); Xfree(deviceName); return psp; handle_error: Xfree(driverName); Xfree(deviceName); XFree(psp); /* FIXME: clean up here */ return NULL; }
static gboolean try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) { drm_magic_t magic; const gchar *exts, *glexts; if (backend_wayland->drm_fd < 0) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Failed to open drm device"); return FALSE; } glexts = glGetString(GL_EXTENSIONS); exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); if (!_cogl_check_extension ("EGL_KHR_image_base", exts) || !_cogl_check_extension ("EGL_MESA_drm_image", exts) || !_cogl_check_extension ("GL_OES_EGL_image", glexts)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Missing EGL extensions"); return FALSE; } backend_wayland->create_drm_image = (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA"); backend_wayland->destroy_image = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR"); backend_wayland->export_drm_image = (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA"); backend_wayland->image_target_texture_2d = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES"); if (backend_wayland->create_drm_image == NULL || backend_wayland->destroy_image == NULL || backend_wayland->export_drm_image == NULL || backend_wayland->image_target_texture_2d == NULL) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Missing EGL extensions"); return FALSE; } if (drmGetMagic (backend_wayland->drm_fd, &magic)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Failed to get drm magic"); return FALSE; } wl_drm_authenticate (backend_wayland->wayland_drm, magic); wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE); while (!backend_wayland->authenticated) wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); return TRUE; };
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; }
LOCAL dri_state_t* getDRI2State(Display* dpy, int screen, char **driver_name) { int major, minor; int error_base; int event_base; char *device_name = NULL; drm_magic_t magic; char * internal_driver_name = NULL; int fd = -1; dri_state_t* state = NULL; if (!VA_DRI2QueryExtension(dpy, &event_base, &error_base)) goto err_out; if (!VA_DRI2QueryVersion(dpy, &major, &minor)) goto err_out; if (!VA_DRI2Connect(dpy, RootWindow(dpy, screen), &internal_driver_name, &device_name)) goto err_out; fd = open(device_name, O_RDWR); if (fd < 0) goto err_out; if (drmGetMagic(fd, &magic)) goto err_out; if (!VA_DRI2Authenticate(dpy, RootWindow(dpy, screen), magic)) goto err_out; if(driver_name) *driver_name = internal_driver_name; else Xfree(internal_driver_name); state = dri_state_new(); state->fd = fd; state->x11_dpy = dpy; state->x11_screen = screen; state->driConnectedFlag = DRI2; if (device_name) Xfree(device_name); return state; err_out: if (device_name) Xfree(device_name); if (internal_driver_name) Xfree(internal_driver_name); if(driver_name) *driver_name = NULL; if (fd >= 0) close(fd); if (driver_name) *driver_name = NULL; return state; }
/** * Perform the required libGL-side initialization and call the client-side * driver's \c __driCreateNewScreen function. * * \param dpy Display pointer. * \param scrn Screen number on the display. * \param psc DRI screen information. * \param driDpy DRI display information. * \param createNewScreen Pointer to the client-side driver's * \c __driCreateNewScreen function. * \returns A pointer to the \c __DRIscreen structure returned by * the client-side driver on success, or \c NULL on failure. */ static void * CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, struct dri_display * driDpy) { void *psp = NULL; drm_handle_t hSAREA; drmAddress pSAREA = MAP_FAILED; char *BusID; __DRIversion ddx_version; __DRIversion dri_version; __DRIversion drm_version; __DRIframebuffer framebuffer; int fd = -1; int status; drm_magic_t magic; drmVersionPtr version; int newlyopened; char *driverName; drm_handle_t hFB; int junk; const __DRIconfig **driver_configs; struct glx_config *visual, *configs = NULL, *visuals = NULL; /* DRI protocol version. */ dri_version.major = driDpy->driMajor; dri_version.minor = driDpy->driMinor; dri_version.patch = driDpy->driPatch; framebuffer.base = MAP_FAILED; framebuffer.dev_priv = NULL; framebuffer.size = 0; if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { ErrorMessageF("XF86DRIOpenConnection failed\n"); goto handle_error; } fd = drmOpenOnce(NULL, BusID, &newlyopened); free(BusID); /* No longer needed */ if (fd < 0) { ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); goto handle_error; } if (drmGetMagic(fd, &magic)) { ErrorMessageF("drmGetMagic failed\n"); goto handle_error; } version = drmGetVersion(fd); if (version) { drm_version.major = version->version_major; drm_version.minor = version->version_minor; drm_version.patch = version->version_patchlevel; drmFreeVersion(version); } else { drm_version.major = -1; drm_version.minor = -1; drm_version.patch = -1; } if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { ErrorMessageF("XF86DRIAuthConnection failed\n"); goto handle_error; } /* Get device name (like "radeon") and the ddx version numbers. * We'll check the version in each DRI driver's "createNewScreen" * function. */ if (!XF86DRIGetClientDriverName(dpy, scrn, &ddx_version.major, &ddx_version.minor, &ddx_version.patch, &driverName)) { ErrorMessageF("XF86DRIGetClientDriverName failed\n"); goto handle_error; } free(driverName); /* No longer needed. */ /* * Get device-specific info. pDevPriv will point to a struct * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that * has information about the screen size, depth, pitch, ancilliary * buffers, DRM mmap handles, etc. */ if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, &framebuffer.size, &framebuffer.stride, &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { ErrorMessageF("XF86DRIGetDeviceInfo failed\n"); goto handle_error; } framebuffer.width = DisplayWidth(dpy, scrn); framebuffer.height = DisplayHeight(dpy, scrn); /* Map the framebuffer region. */ status = drmMap(fd, hFB, framebuffer.size, (drmAddressPtr) & framebuffer.base); if (status != 0) { ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status)); goto handle_error; } /* Map the SAREA region. Further mmap regions may be setup in * each DRI driver's "createNewScreen" function. */ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); if (status != 0) { ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status)); goto handle_error; } psp = (*psc->legacy->createNewScreen) (scrn, &ddx_version, &dri_version, &drm_version, &framebuffer, pSAREA, fd, loader_extensions, &driver_configs, psc); if (psp == NULL) { ErrorMessageF("Calling driver entry point failed\n"); goto handle_error; } configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); if (!configs || !visuals) goto handle_error; glx_config_destroy_list(psc->base.configs); psc->base.configs = configs; glx_config_destroy_list(psc->base.visuals); psc->base.visuals = visuals; psc->driver_configs = driver_configs; /* Visuals with depth != screen depth are subject to automatic compositing * in the X server, so DRI1 can't render to them properly. Mark them as * non-conformant to prevent apps from picking them up accidentally. */ for (visual = psc->base.visuals; visual; visual = visual->next) { XVisualInfo template;
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; }