struct vl_screen * vl_dri3_screen_create(Display *display, int screen) { struct vl_dri3_screen *scrn; const xcb_query_extension_reply_t *extension; xcb_dri3_open_cookie_t open_cookie; xcb_dri3_open_reply_t *open_reply; xcb_get_geometry_cookie_t geom_cookie; xcb_get_geometry_reply_t *geom_reply; int is_different_gpu; int fd; assert(display); scrn = CALLOC_STRUCT(vl_dri3_screen); if (!scrn) return NULL; scrn->conn = XGetXCBConnection(display); if (!scrn->conn) goto free_screen; xcb_prefetch_extension_data(scrn->conn , &xcb_dri3_id); xcb_prefetch_extension_data(scrn->conn, &xcb_present_id); extension = xcb_get_extension_data(scrn->conn, &xcb_dri3_id); if (!(extension && extension->present)) goto free_screen; extension = xcb_get_extension_data(scrn->conn, &xcb_present_id); if (!(extension && extension->present)) goto free_screen; open_cookie = xcb_dri3_open(scrn->conn, RootWindow(display, screen), None); open_reply = xcb_dri3_open_reply(scrn->conn, open_cookie, NULL); if (!open_reply) goto free_screen; if (open_reply->nfd != 1) { free(open_reply); goto free_screen; } fd = xcb_dri3_open_reply_fds(scrn->conn, open_reply)[0]; if (fd < 0) { free(open_reply); goto free_screen; } fcntl(fd, F_SETFD, FD_CLOEXEC); free(open_reply); fd = loader_get_user_preferred_fd(fd, &is_different_gpu); /* TODO support different GPU */ if (is_different_gpu) goto close_fd; geom_cookie = xcb_get_geometry(scrn->conn, RootWindow(display, screen)); geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL); if (!geom_reply) goto close_fd; /* TODO support depth other than 24 */ if (geom_reply->depth != 24) { free(geom_reply); goto close_fd; } free(geom_reply); 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_dri3_screen_destroy; scrn->base.texture_from_drawable = vl_dri3_screen_texture_from_drawable; scrn->base.get_dirty_area = vl_dri3_screen_get_dirty_area; scrn->base.get_timestamp = vl_dri3_screen_get_timestamp; scrn->base.set_next_timestamp = vl_dri3_screen_set_next_timestamp; scrn->base.get_private = vl_dri3_screen_get_private; scrn->base.pscreen->flush_frontbuffer = vl_dri3_flush_frontbuffer; return &scrn->base; release_pipe: if (scrn->base.dev) { pipe_loader_release(&scrn->base.dev, 1); fd = -1; } close_fd: if (fd != -1) close(fd); free_screen: FREE(scrn); return NULL; }
XA_EXPORT struct xa_tracker * xa_tracker_create(int drm_fd) { struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker)); enum xa_surface_type stype; unsigned int num_formats; int loader_fd; if (!xa) return NULL; loader_fd = dup(drm_fd); if (loader_fd == -1) return NULL; if (pipe_loader_drm_probe_fd(&xa->dev, loader_fd, false)) xa->screen = pipe_loader_create_screen(xa->dev, PIPE_SEARCH_DIR); if (!xa->screen) goto out_no_screen; xa->default_ctx = xa_context_create(xa); if (!xa->default_ctx) goto out_no_pipe; num_formats = 0; for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) num_formats += num_preferred[stype]; num_formats += 1; xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats)); if (!xa->supported_formats) goto out_sf_alloc_fail; xa->supported_formats[0] = xa_format_unknown; num_formats = 1; memset(xa->format_map, 0, sizeof(xa->format_map)); for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) { unsigned int bind = stype_bind[stype]; enum xa_formats xa_format; int i; for (i = 0; i < num_preferred[stype]; ++i) { xa_format = preferred[stype][i]; struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format); if (xa->screen->is_format_supported(xa->screen, fdesc.format, PIPE_TEXTURE_2D, 0, bind)) { if (xa->format_map[stype][0] == 0) xa->format_map[stype][0] = num_formats; xa->format_map[stype][1] = num_formats; xa->supported_formats[num_formats++] = xa_format; } } } return xa; out_sf_alloc_fail: xa_context_destroy(xa->default_ctx); out_no_pipe: xa->screen->destroy(xa->screen); out_no_screen: if (xa->dev) pipe_loader_release(&xa->dev, 1); free(xa); return NULL; }
int pipe_loader_drm_probe(struct pipe_loader_device **devs, int ndev) { int i, k, fd, num_render_node_devs; int j = 0; struct { unsigned vendor_id; unsigned chip_id; } render_node_devs[DRM_RENDER_NODE_MAX_NODES]; /* Look for render nodes first */ for (i = DRM_RENDER_NODE_MIN_MINOR, j = 0; i <= DRM_RENDER_NODE_MAX_MINOR; i++) { fd = open_drm_render_node_minor(i); struct pipe_loader_device *dev; if (fd < 0) continue; if (!pipe_loader_drm_probe_fd(&dev, fd, false)) { close(fd); continue; } render_node_devs[j].vendor_id = dev->u.pci.vendor_id; render_node_devs[j].chip_id = dev->u.pci.chip_id; if (j < ndev) { devs[j] = dev; } else { close(fd); dev->ops->release(&dev); } j++; } num_render_node_devs = j; /* Next look for drm devices. */ for (i = 0; i < DRM_MAX_MINOR; i++) { struct pipe_loader_device *dev; boolean duplicate = FALSE; fd = open_drm_minor(i); if (fd < 0) continue; if (!pipe_loader_drm_probe_fd(&dev, fd, true)) { close(fd); continue; } /* Check to make sure we aren't already accessing this device via * render nodes. */ for (k = 0; k < num_render_node_devs; k++) { if (dev->u.pci.vendor_id == render_node_devs[k].vendor_id && dev->u.pci.chip_id == render_node_devs[k].chip_id) { close(fd); dev->ops->release(&dev); duplicate = TRUE; break; } } if (duplicate) continue; if (j < ndev) { devs[j] = dev; } else { dev->ops->release(&dev); } j++; } return j; }
static HRESULT WINAPI drm_create_adapter( int fd, ID3DAdapter9 **ppAdapter ) { struct d3dadapter9drm_context *ctx = CALLOC_STRUCT(d3dadapter9drm_context); HRESULT hr; int i; const char *paths[] = { getenv("D3D9_DRIVERS_PATH"), getenv("D3D9_DRIVERS_DIR"), PIPE_SEARCH_DIR }; if (!ctx) { return E_OUTOFMEMORY; } ctx->base.resource_from_present = drm_resource_from_present; ctx->base.destroy = drm_destroy; /* use pipe-loader to dlopen appropriate drm driver */ if (!pipe_loader_drm_probe_fd(&ctx->dev, fd, FALSE)) { DBG("Failed to probe drm fd %d.\n", fd); FREE(ctx); close(fd); return D3DERR_DRIVERINTERNALERROR; } /* use pipe-loader to create a drm screen (hal) */ ctx->base.hal = NULL; for (i = 0; !ctx->base.hal && i < Elements(paths); ++i) { if (!paths[i]) { continue; } ctx->base.hal = pipe_loader_create_screen(ctx->dev, paths[i]); } if (!ctx->base.hal) { DBG("Unable to load requested driver.\n"); pipe_loader_release(&ctx->dev, 1); FREE(ctx); return D3DERR_DRIVERINTERNALERROR; } /* wrap it to create a software screen that can share resources */ if (pipe_loader_sw_probe_wrapped(&ctx->swdev, ctx->base.hal)) { ctx->base.ref = NULL; for (i = 0; !ctx->base.ref && i < Elements(paths); ++i) { if (!paths[i]) { continue; } ctx->base.ref = pipe_loader_create_screen(ctx->swdev, paths[i]); } } if (!ctx->base.ref) { DBG("Couldn't wrap drm screen to swrast screen. Software devices " "will be unavailable.\n"); } /* read out PCI info */ read_descriptor(&ctx->base, fd); /* create and return new ID3DAdapter9 */ hr = NineAdapter9_new(&ctx->base, (struct NineAdapter9 **)ppAdapter); if (FAILED(hr)) { if (ctx->swdev) { pipe_loader_release(&ctx->swdev, 1); } pipe_loader_release(&ctx->dev, 1); FREE(ctx); return hr; } return D3D_OK; }
static HRESULT WINAPI drm_create_adapter( int fd, ID3DAdapter9 **ppAdapter ) { struct d3dadapter9drm_context *ctx = CALLOC_STRUCT(d3dadapter9drm_context); HRESULT hr; bool different_device; driOptionCache defaultInitOptions; driOptionCache userInitOptions; int throttling_value_user = -2; int override_vendorid = -1; if (!ctx) { return E_OUTOFMEMORY; } ctx->base.destroy = drm_destroy; /* Although the fd is provided from external source, mesa/nine * takes ownership of it. */ fd = loader_get_user_preferred_fd(fd, &different_device); ctx->fd = fd; ctx->base.linear_framebuffer = different_device; if (!pipe_loader_drm_probe_fd(&ctx->dev, fd)) { ERR("Failed to probe drm fd %d.\n", fd); FREE(ctx); close(fd); return D3DERR_DRIVERINTERNALERROR; } ctx->base.hal = pipe_loader_create_screen(ctx->dev); if (!ctx->base.hal) { ERR("Unable to load requested driver.\n"); drm_destroy(&ctx->base); return D3DERR_DRIVERINTERNALERROR; } if (!ctx->base.hal->get_param(ctx->base.hal, PIPE_CAP_DMABUF)) { ERR("The driver is not capable of dma-buf sharing." "Abandon to load nine state tracker\n"); drm_destroy(&ctx->base); return D3DERR_DRIVERINTERNALERROR; } /* Previously was set to PIPE_CAP_MAX_FRAMES_IN_FLIGHT, * but the change of value of this cap to 1 seems to cause * regressions. */ ctx->base.throttling_value = 2; ctx->base.throttling = ctx->base.throttling_value > 0; driParseOptionInfo(&defaultInitOptions, __driConfigOptionsNine); driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0, "nine", NULL); if (driCheckOption(&userInitOptions, "throttle_value", DRI_INT)) { throttling_value_user = driQueryOptioni(&userInitOptions, "throttle_value"); if (throttling_value_user == -1) ctx->base.throttling = FALSE; else if (throttling_value_user >= 0) { ctx->base.throttling = TRUE; ctx->base.throttling_value = throttling_value_user; } } if (driCheckOption(&userInitOptions, "vblank_mode", DRI_ENUM)) ctx->base.vblank_mode = driQueryOptioni(&userInitOptions, "vblank_mode"); else ctx->base.vblank_mode = 1; if (driCheckOption(&userInitOptions, "thread_submit", DRI_BOOL)) ctx->base.thread_submit = driQueryOptionb(&userInitOptions, "thread_submit"); else ctx->base.thread_submit = different_device; if (driCheckOption(&userInitOptions, "override_vendorid", DRI_INT)) { override_vendorid = driQueryOptioni(&userInitOptions, "override_vendorid"); } if (driCheckOption(&userInitOptions, "discard_delayed_release", DRI_BOOL)) ctx->base.discard_delayed_release = driQueryOptionb(&userInitOptions, "discard_delayed_release"); else ctx->base.discard_delayed_release = TRUE; if (driCheckOption(&userInitOptions, "tearfree_discard", DRI_BOOL)) ctx->base.tearfree_discard = driQueryOptionb(&userInitOptions, "tearfree_discard"); else ctx->base.tearfree_discard = FALSE; if (ctx->base.tearfree_discard && !ctx->base.discard_delayed_release) { ERR("tearfree_discard requires discard_delayed_release\n"); ctx->base.tearfree_discard = FALSE; } if (driCheckOption(&userInitOptions, "csmt_force", DRI_INT)) ctx->base.csmt_force = driQueryOptioni(&userInitOptions, "csmt_force"); else ctx->base.csmt_force = -1; if (driCheckOption(&userInitOptions, "dynamic_texture_workaround", DRI_BOOL)) ctx->base.dynamic_texture_workaround = driQueryOptionb(&userInitOptions, "dynamic_texture_workaround"); else ctx->base.dynamic_texture_workaround = FALSE; if (driCheckOption(&userInitOptions, "shader_inline_constants", DRI_BOOL)) ctx->base.shader_inline_constants = driQueryOptionb(&userInitOptions, "shader_inline_constants"); else ctx->base.shader_inline_constants = FALSE; driDestroyOptionCache(&userInitOptions); driDestroyOptionInfo(&defaultInitOptions); /* wrap it to create a software screen that can share resources */ if (pipe_loader_sw_probe_wrapped(&ctx->swdev, ctx->base.hal)) ctx->base.ref = pipe_loader_create_screen(ctx->swdev); if (!ctx->base.ref) { ERR("Couldn't wrap drm screen to swrast screen. Software devices " "will be unavailable.\n"); } /* read out PCI info */ read_descriptor(&ctx->base, fd, override_vendorid); /* create and return new ID3DAdapter9 */ hr = NineAdapter9_new(&ctx->base, (struct NineAdapter9 **)ppAdapter); if (FAILED(hr)) { drm_destroy(&ctx->base); return hr; } return D3D_OK; }
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; }
static HRESULT WINAPI drm_create_adapter( int fd, ID3DAdapter9 **ppAdapter ) { struct d3dadapter9drm_context *ctx = CALLOC_STRUCT(d3dadapter9drm_context); HRESULT hr; int different_device; const struct drm_conf_ret *throttle_ret = NULL; const struct drm_conf_ret *dmabuf_ret = NULL; driOptionCache defaultInitOptions; driOptionCache userInitOptions; int throttling_value_user = -2; #if !GALLIUM_STATIC_TARGETS const char *paths[] = { getenv("D3D9_DRIVERS_PATH"), getenv("D3D9_DRIVERS_DIR"), PIPE_SEARCH_DIR }; #endif if (!ctx) { return E_OUTOFMEMORY; } ctx->base.destroy = drm_destroy; fd = loader_get_user_preferred_fd(fd, &different_device); ctx->fd = fd; ctx->base.linear_framebuffer = !!different_device; #if GALLIUM_STATIC_TARGETS ctx->base.hal = dd_create_screen(fd); #else /* use pipe-loader to dlopen appropriate drm driver */ if (!pipe_loader_drm_probe_fd(&ctx->dev, fd)) { ERR("Failed to probe drm fd %d.\n", fd); FREE(ctx); close(fd); return D3DERR_DRIVERINTERNALERROR; } /* use pipe-loader to create a drm screen (hal) */ ctx->base.hal = NULL; for (i = 0; !ctx->base.hal && i < Elements(paths); ++i) { if (!paths[i]) { continue; } ctx->base.hal = pipe_loader_create_screen(ctx->dev, paths[i]); } #endif if (!ctx->base.hal) { ERR("Unable to load requested driver.\n"); drm_destroy(&ctx->base); return D3DERR_DRIVERINTERNALERROR; } #if GALLIUM_STATIC_TARGETS dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD); throttle_ret = dd_configuration(DRM_CONF_THROTTLE); #else dmabuf_ret = pipe_loader_configuration(ctx->dev, DRM_CONF_SHARE_FD); throttle_ret = pipe_loader_configuration(ctx->dev, DRM_CONF_THROTTLE); #endif // GALLIUM_STATIC_TARGETS if (!dmabuf_ret || !dmabuf_ret->val.val_bool) { ERR("The driver is not capable of dma-buf sharing." "Abandon to load nine state tracker\n"); drm_destroy(&ctx->base); return D3DERR_DRIVERINTERNALERROR; } if (throttle_ret && throttle_ret->val.val_int != -1) { ctx->base.throttling = TRUE; ctx->base.throttling_value = throttle_ret->val.val_int; } else ctx->base.throttling = FALSE; driParseOptionInfo(&defaultInitOptions, __driConfigOptionsNine); driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0, "nine"); if (driCheckOption(&userInitOptions, "throttle_value", DRI_INT)) { throttling_value_user = driQueryOptioni(&userInitOptions, "throttle_value"); if (throttling_value_user == -1) ctx->base.throttling = FALSE; else if (throttling_value_user >= 0) { ctx->base.throttling = TRUE; ctx->base.throttling_value = throttling_value_user; } } if (driCheckOption(&userInitOptions, "vblank_mode", DRI_ENUM)) ctx->base.vblank_mode = driQueryOptioni(&userInitOptions, "vblank_mode"); else ctx->base.vblank_mode = 1; if (driCheckOption(&userInitOptions, "thread_submit", DRI_BOOL)) { ctx->base.thread_submit = driQueryOptionb(&userInitOptions, "thread_submit"); if (ctx->base.thread_submit && (throttling_value_user == -2 || throttling_value_user == 0)) { ctx->base.throttling_value = 0; } else if (ctx->base.thread_submit) { DBG("You have set a non standard throttling value in combination with thread_submit." "We advise to use a throttling value of -2/0"); } if (ctx->base.thread_submit && !different_device) DBG("You have set thread_submit but do not use a different device than the server." "You should not expect any benefit."); } driDestroyOptionCache(&userInitOptions); driDestroyOptionInfo(&defaultInitOptions); #if GALLIUM_STATIC_TARGETS ctx->base.ref = ninesw_create_screen(ctx->base.hal); #else /* wrap it to create a software screen that can share resources */ if (pipe_loader_sw_probe_wrapped(&ctx->swdev, ctx->base.hal)) { ctx->base.ref = NULL; for (i = 0; !ctx->base.ref && i < Elements(paths); ++i) { if (!paths[i]) { continue; } ctx->base.ref = pipe_loader_create_screen(ctx->swdev, paths[i]); } } #endif if (!ctx->base.ref) { ERR("Couldn't wrap drm screen to swrast screen. Software devices " "will be unavailable.\n"); } /* read out PCI info */ read_descriptor(&ctx->base, fd); /* create and return new ID3DAdapter9 */ hr = NineAdapter9_new(&ctx->base, (struct NineAdapter9 **)ppAdapter); if (FAILED(hr)) { drm_destroy(&ctx->base); return hr; } return D3D_OK; }
struct vl_screen * vl_dri3_screen_create(Display *display, int screen) { struct vl_dri3_screen *scrn; const xcb_query_extension_reply_t *extension; xcb_dri3_open_cookie_t open_cookie; xcb_dri3_open_reply_t *open_reply; xcb_get_geometry_cookie_t geom_cookie; xcb_get_geometry_reply_t *geom_reply; xcb_xfixes_query_version_cookie_t xfixes_cookie; xcb_xfixes_query_version_reply_t *xfixes_reply; xcb_generic_error_t *error; int fd; assert(display); scrn = CALLOC_STRUCT(vl_dri3_screen); if (!scrn) return NULL; scrn->conn = XGetXCBConnection(display); if (!scrn->conn) goto free_screen; xcb_prefetch_extension_data(scrn->conn , &xcb_dri3_id); xcb_prefetch_extension_data(scrn->conn, &xcb_present_id); xcb_prefetch_extension_data (scrn->conn, &xcb_xfixes_id); extension = xcb_get_extension_data(scrn->conn, &xcb_dri3_id); if (!(extension && extension->present)) goto free_screen; extension = xcb_get_extension_data(scrn->conn, &xcb_present_id); if (!(extension && extension->present)) goto free_screen; extension = xcb_get_extension_data(scrn->conn, &xcb_xfixes_id); if (!(extension && extension->present)) goto free_screen; xfixes_cookie = xcb_xfixes_query_version(scrn->conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); xfixes_reply = xcb_xfixes_query_version_reply(scrn->conn, xfixes_cookie, &error); if (!xfixes_reply || error || xfixes_reply->major_version < 2) { free(error); free(xfixes_reply); goto free_screen; } free(xfixes_reply); open_cookie = xcb_dri3_open(scrn->conn, RootWindow(display, screen), None); open_reply = xcb_dri3_open_reply(scrn->conn, open_cookie, NULL); if (!open_reply) goto free_screen; if (open_reply->nfd != 1) { free(open_reply); goto free_screen; } fd = xcb_dri3_open_reply_fds(scrn->conn, open_reply)[0]; if (fd < 0) { free(open_reply); goto free_screen; } fcntl(fd, F_SETFD, FD_CLOEXEC); free(open_reply); fd = loader_get_user_preferred_fd(fd, &scrn->is_different_gpu); geom_cookie = xcb_get_geometry(scrn->conn, RootWindow(display, screen)); geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL); if (!geom_reply) goto close_fd; scrn->base.xcb_screen = dri3_get_screen_for_root(scrn->conn, geom_reply->root); if (!scrn->base.xcb_screen) { free(geom_reply); goto close_fd; } /* TODO support depth other than 24 or 30 */ if (geom_reply->depth != 24 && geom_reply->depth != 30) { free(geom_reply); goto close_fd; } scrn->base.color_depth = geom_reply->depth; free(geom_reply); 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->pipe = scrn->base.pscreen->context_create(scrn->base.pscreen, NULL, 0); if (!scrn->pipe) goto no_context; scrn->base.destroy = vl_dri3_screen_destroy; scrn->base.texture_from_drawable = vl_dri3_screen_texture_from_drawable; scrn->base.get_dirty_area = vl_dri3_screen_get_dirty_area; scrn->base.get_timestamp = vl_dri3_screen_get_timestamp; scrn->base.set_next_timestamp = vl_dri3_screen_set_next_timestamp; scrn->base.get_private = vl_dri3_screen_get_private; scrn->base.pscreen->flush_frontbuffer = vl_dri3_flush_frontbuffer; scrn->base.set_back_texture_from_output = vl_dri3_screen_set_back_texture_from_output; scrn->next_back = 1; return &scrn->base; no_context: scrn->base.pscreen->destroy(scrn->base.pscreen); release_pipe: if (scrn->base.dev) { pipe_loader_release(&scrn->base.dev, 1); fd = -1; } close_fd: if (fd != -1) close(fd); free_screen: FREE(scrn); return NULL; }