diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index 334e57ad57a..c3978e920e2 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -667,6 +667,11 @@ dri2_initialize_drm(_EGLDisplay *disp) goto cleanup; } + if (!dri2_dpy->gbm_dri->screen) { + err = "DRI2: DRI2 not supported by the gbm backend"; + goto cleanup; + } + dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->driver_name); dri2_detect_swrast_kopper(disp); diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c index 6640f16da77..ff1b5fc97ad 100644 --- a/src/gbm/backends/dri/gbm_dri.c +++ b/src/gbm/backends/dri/gbm_dri.c @@ -32,6 +32,7 @@ #include #include #include +#include /* for O_RDWR, which DRM_RDWR is defined as */ #include #include #include @@ -277,6 +278,7 @@ dri_screen_create_for_driver(struct gbm_dri_device *dri, char *driver_name, bool fail: free(dri->driver_name); + dri->driver_name = NULL; return -1; } @@ -384,7 +386,7 @@ gbm_dri_is_format_supported(struct gbm_device *gbm, /* If there is no query, fall back to the small table which was originally * here. */ - if (!dri->has_dmabuf_import) { + if (!dri->screen || !dri->has_dmabuf_import) { switch (format) { case GBM_FORMAT_XRGB8888: case GBM_FORMAT_ARGB8888: @@ -411,7 +413,7 @@ gbm_dri_get_format_modifier_plane_count(struct gbm_device *gbm, struct gbm_dri_device *dri = gbm_dri_device(gbm); uint64_t plane_count; - if (!dri->has_dmabuf_import) + if (!dri->screen || !dri->has_dmabuf_import) return -1; format = core->v0.format_canonicalize(format); @@ -446,8 +448,19 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo) struct gbm_dri_bo *bo = gbm_dri_bo(_bo); int fd; - if (bo->image == NULL) + if (bo->image == NULL) { +#ifdef HAVE_LIBDRM + struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); + if (dri->has_dmabuf_export) { + int ret; + int prime_fd = -1; + ret = drmPrimeHandleToFD(dri->base.v0.fd, bo->handle, DRM_RDWR, &prime_fd); + if (!ret) + return prime_fd; + } +#endif return -1; + } if (!dri2_query_image(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd)) return -1; @@ -664,6 +677,43 @@ gbm_dri_bo_destroy(struct gbm_bo *_bo) free(bo); } +static struct gbm_bo * +dumb_bo_from_fd(struct gbm_device *gbm, + struct gbm_import_fd_data *fd_data) +{ +#ifdef HAVE_LIBDRM + struct gbm_dri_bo *bo; + int ret; + uint32_t handle; + + bo = calloc(1, sizeof *bo); + if (bo == NULL) { + errno = ENOMEM; + return NULL; + } + + ret = drmPrimeFDToHandle(gbm->v0.fd, fd_data->fd, &handle); + if (ret) { + free(bo); + return NULL; + } + + bo->base.gbm = gbm; + bo->base.v0.width = fd_data->width; + bo->base.v0.height = fd_data->height; + bo->base.v0.stride = fd_data->stride; + bo->base.v0.format = fd_data->format; + bo->base.v0.handle.u32 = handle; + bo->handle = handle; + bo->size = fd_data->stride * fd_data->height; + + return &bo->base; +#else + errno = ENOSYS; + return NULL; +#endif +} + static struct gbm_bo * gbm_dri_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer, uint32_t usage) @@ -738,6 +788,9 @@ gbm_dri_bo_import(struct gbm_device *gbm, * the sARGB format. */ fourcc = core->v0.format_canonicalize(fd_data->format); + if (!dri->screen) + return dumb_bo_from_fd(gbm, fd_data); + image = dri2_from_dma_bufs(dri->screen, fd_data->width, fd_data->height, @@ -766,6 +819,11 @@ gbm_dri_bo_import(struct gbm_device *gbm, * the sARGB format. */ fourcc = core->v0.format_canonicalize(fd_data->format); + if (!dri->screen) { + errno = EINVAL; + return NULL; + } + image = dri2_from_dma_bufs(dri->screen, fd_data->width, fd_data->height, fourcc, fd_data->modifier, @@ -899,7 +957,7 @@ gbm_dri_bo_create(struct gbm_device *gbm, format = core->v0.format_canonicalize(format); - if (usage & GBM_BO_USE_WRITE || !dri->has_dmabuf_export) + if (usage & GBM_BO_USE_WRITE || !dri->screen || !dri->has_dmabuf_export) return create_dumb(gbm, width, height, format, usage); bo = calloc(1, sizeof *bo); @@ -1053,6 +1111,11 @@ gbm_dri_bo_map(struct gbm_bo *_bo, return *map_data; } + if (!dri->screen) { + errno = EINVAL; + return NULL; + } + mtx_lock(&dri->mutex); if (!dri->context) { unsigned error; @@ -1110,6 +1173,11 @@ gbm_dri_surface_create(struct gbm_device *gbm, if (count) assert(modifiers); + if (!dri->screen) { + errno = ENOSYS; + return NULL; + } + if (count > 0 && !dri->screen->base.screen->resource_create_with_modifiers) { errno = ENOSYS; return NULL; @@ -1177,9 +1245,12 @@ dri_destroy(struct gbm_device *gbm) if (dri->context) driDestroyContext(dri->context); - driDestroyScreen(dri->screen); - for (i = 0; dri->driver_configs[i]; i++) - free((struct dri_config *) dri->driver_configs[i]); + if (dri->screen) + driDestroyScreen(dri->screen); + if (dri->driver_configs) + for (i = 0; dri->driver_configs[i]; i++) + free((struct dri_config *) dri->driver_configs[i]); + free(dri->driver_configs); free(dri->driver_name); @@ -1235,26 +1306,31 @@ dri_device_create(int fd, uint32_t gbm_backend_version) ret = dri_screen_create_sw(dri, false); } - if (ret) - goto err_dri; - - struct dri_screen *screen = dri->screen; - struct pipe_screen *pscreen = screen->base.screen; + if (!ret) { + struct dri_screen *screen = dri->screen; + struct pipe_screen *pscreen = screen->base.screen; #ifdef HAVE_LIBDRM - if (pscreen->caps.dmabuf & DRM_PRIME_CAP_IMPORT) - dri->has_dmabuf_import = true; - if (pscreen->caps.dmabuf & DRM_PRIME_CAP_EXPORT) - dri->has_dmabuf_export = true; + if (pscreen->caps.dmabuf & DRM_PRIME_CAP_IMPORT) + dri->has_dmabuf_import = true; + if (pscreen->caps.dmabuf & DRM_PRIME_CAP_EXPORT) + dri->has_dmabuf_export = true; #endif - dri->has_compression_modifiers = pscreen->query_compression_rates && - pscreen->query_compression_modifiers; + dri->has_compression_modifiers = pscreen->query_compression_rates && + pscreen->query_compression_modifiers; + } else { + if (!dri->driver_name) + dri->driver_name = strdup("dumb"); +#ifdef HAVE_LIBDRM + uint64_t value = 0; + ret = drmGetCap(fd, DRM_CAP_PRIME, &value); + if (ret == 0) { + dri->has_dmabuf_import = !!(value & DRM_PRIME_CAP_IMPORT); + dri->has_dmabuf_export = !!(value & DRM_PRIME_CAP_EXPORT); + } +#endif + } return &dri->base; - -err_dri: - free(dri); - - return NULL; } struct gbm_backend gbm_dri_backend = {