diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 5d2107abf..6fbbeb3c6 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -26,7 +26,8 @@ * Zhigang Gong * */ -#include + +#include "dix-config.h" #define GLAMOR_FOR_XORG #include @@ -41,11 +42,10 @@ #include #include -#include "dix/screen_hooks_priv.h" -#include "glamor/glamor_priv.h" -#include "os/bug_priv.h" - #include "glamor_egl.h" + +#include "glamor.h" +#include "glamor_priv.h" #include "glamor_glx_provider.h" #include "dri3.h" @@ -53,12 +53,19 @@ struct glamor_egl_screen_private { EGLDisplay display; EGLContext context; char *device_path; + + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; +#ifdef EGL_MESA_image_dma_buf_export + int has_image_dma_buf_export; +#endif + int fd; + struct gbm_device *gbm; + int dmabuf_capable; char *glvnd_vendor; /* GLVND vendor if forced from options or NULL otherwise */ - struct gbm_device *gbm; - int fd; - int dmabuf_capable; - + CloseScreenProcPtr saved_close_screen; + DestroyPixmapProcPtr saved_destroy_pixmap; xf86FreeScreenProc *saved_free_screen; }; @@ -141,6 +148,22 @@ glamor_egl_get_gbm_device(ScreenPtr screen) return glamor_egl->gbm; } +Bool +glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + PixmapPtr screen_pixmap; + + screen_pixmap = screen->GetScreenPixmap(screen); + + if (!glamor_egl_create_textured_pixmap(screen_pixmap, handle, stride)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to create textured screen."); + return FALSE; + } + return TRUE; +} + static void glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image, Bool used_modifiers) @@ -149,8 +172,6 @@ glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image, glamor_get_pixmap_private(pixmap); EGLImageKHR old; - BUG_RETURN(!pixmap_priv); - old = pixmap_priv->image; if (old) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -213,106 +234,12 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, Bool ret = FALSE; glamor_egl = glamor_egl_get_screen_private(scrn); -#ifdef GBM_BO_FD_FOR_PLANE - uint64_t modifier = gbm_bo_get_modifier(bo); - const int num_planes = gbm_bo_get_plane_count(bo); - int fds[GBM_MAX_PLANES]; - int plane; - int attr_num = 0; - EGLint img_attrs[64] = {0}; - enum PlaneAttrs { - PLANE_FD, - PLANE_OFFSET, - PLANE_PITCH, - PLANE_MODIFIER_LO, - PLANE_MODIFIER_HI, - NUM_PLANE_ATTRS - }; - static const EGLint planeAttrs[][NUM_PLANE_ATTRS] = { - { - EGL_DMA_BUF_PLANE0_FD_EXT, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, - EGL_DMA_BUF_PLANE0_PITCH_EXT, - EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, - }, - { - EGL_DMA_BUF_PLANE1_FD_EXT, - EGL_DMA_BUF_PLANE1_OFFSET_EXT, - EGL_DMA_BUF_PLANE1_PITCH_EXT, - EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, - }, - { - EGL_DMA_BUF_PLANE2_FD_EXT, - EGL_DMA_BUF_PLANE2_OFFSET_EXT, - EGL_DMA_BUF_PLANE2_PITCH_EXT, - EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, - }, - { - EGL_DMA_BUF_PLANE3_FD_EXT, - EGL_DMA_BUF_PLANE3_OFFSET_EXT, - EGL_DMA_BUF_PLANE3_PITCH_EXT, - EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT, - }, - }; - - for (plane = 0; plane < num_planes; plane++) fds[plane] = -1; -#endif glamor_make_current(glamor_priv); -#ifdef GBM_BO_FD_FOR_PLANE - if (glamor_egl->dmabuf_capable) { -#define ADD_ATTR(attrs, num, attr) \ - do { \ - assert(((num) + 1) < (sizeof(attrs) / sizeof((attrs)[0]))); \ - (attrs)[(num)++] = (attr); \ - } while (0) - ADD_ATTR(img_attrs, attr_num, EGL_WIDTH); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_width(bo)); - ADD_ATTR(img_attrs, attr_num, EGL_HEIGHT); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_height(bo)); - ADD_ATTR(img_attrs, attr_num, EGL_LINUX_DRM_FOURCC_EXT); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_format(bo)); - - for (plane = 0; plane < num_planes; plane++) { - fds[plane] = gbm_bo_get_fd_for_plane(bo, plane); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_FD]); - ADD_ATTR(img_attrs, attr_num, fds[plane]); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_OFFSET]); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_offset(bo, plane)); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_PITCH]); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_stride_for_plane(bo, plane)); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_LO]); - ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier & 0xFFFFFFFFULL)); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_HI]); - ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier >> 32ULL)); - } - ADD_ATTR(img_attrs, attr_num, EGL_NONE); -#undef ADD_ATTR - - image = eglCreateImageKHR(glamor_egl->display, - EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, - NULL, - img_attrs); - - for (plane = 0; plane < num_planes; plane++) { - close(fds[plane]); - fds[plane] = -1; - } - } - else -#endif - { - image = eglCreateImageKHR(glamor_egl->display, - EGL_NO_CONTEXT, - EGL_NATIVE_PIXMAP_KHR, bo, NULL); - } - + image = eglCreateImageKHR(glamor_egl->display, + EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, bo, NULL); if (image == EGL_NO_IMAGE_KHR) { glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); goto done; @@ -354,8 +281,6 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) PixmapPtr exported; GCPtr scratch_gc; - BUG_RETURN_VAL(!pixmap_priv, FALSE); - if (pixmap_priv->image && (modifiers_ok || !pixmap_priv->used_modifiers)) return TRUE; @@ -391,30 +316,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) glamor_get_modifiers(screen, format, &num_modifiers, &modifiers); - if (num_modifiers > 0) { -#ifdef GBM_BO_WITH_MODIFIERS2 - /* TODO: Is scanout ever used? If so, where? */ - bo = gbm_bo_create_with_modifiers2(glamor_egl->gbm, width, height, - format, modifiers, num_modifiers, - GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); - if (!bo) { - /* something failed, try again without GBM_BO_USE_SCANOUT */ - /* maybe scanout does work, but modifiers aren't supported */ - /* we handle this case on the fallback path */ - bo = gbm_bo_create_with_modifiers2(glamor_egl->gbm, width, height, - format, modifiers, num_modifiers, - GBM_BO_USE_RENDERING); -#if 0 - if (bo) { - /* TODO: scanout failed, but regular buffer succeeded, maybe log something? */ - } -#endif - } -#else - bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height, - format, modifiers, num_modifiers); -#endif - } + bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height, + format, modifiers, num_modifiers); if (bo) used_modifiers = TRUE; free(modifiers); @@ -423,27 +326,12 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) if (!bo) { - /* TODO: Is scanout ever used? If so, where? */ bo = gbm_bo_create(glamor_egl->gbm, width, height, format, #ifdef GLAMOR_HAS_GBM_LINEAR (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ? GBM_BO_USE_LINEAR : 0) | #endif GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); - if (!bo) { - /* something failed, try again without GBM_BO_USE_SCANOUT */ - bo = gbm_bo_create(glamor_egl->gbm, width, height, format, -#ifdef GLAMOR_HAS_GBM_LINEAR - (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ? - GBM_BO_USE_LINEAR : 0) | - GBM_BO_USE_RENDERING); -#endif -#if 0 - if (bo) { - /* TODO: scanout failed, but regular buffer succeeded, maybe log something? */ - } -#endif - } } if (!bo) { @@ -461,7 +349,7 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to make %dx%dx%dbpp pixmap from GBM bo\n", width, height, pixmap->drawable.bitsPerPixel); - dixDestroyPixmap(exported, 0); + screen->DestroyPixmap(exported); gbm_bo_destroy(bo); return FALSE; } @@ -482,7 +370,7 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) /* Swap the devKind into the original pixmap, reflecting the bo's stride */ screen->ModifyPixmapHeader(pixmap, 0, 0, 0, 0, exported->devKind, NULL); - dixDestroyPixmap(exported, 0); + screen->DestroyPixmap(exported); return TRUE; } @@ -494,14 +382,58 @@ glamor_gbm_bo_from_pixmap_internal(ScreenPtr screen, PixmapPtr pixmap) glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - - BUG_RETURN_VAL(!pixmap_priv, NULL); + struct gbm_bo* ret = NULL; +#ifdef EGL_MESA_image_dma_buf_export + int fourcc = 0; + int num_planes = 0; + struct gbm_import_fd_modifier_data fd_modifier_data; + EGLuint64KHR modifiers[GBM_MAX_PLANES] = {0}; +#endif if (!pixmap_priv->image) return NULL; - return gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, - pixmap_priv->image, GBM_BO_USE_RENDERING); + ret = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, + pixmap_priv->image, 0); + +#ifdef EGL_MESA_image_dma_buf_export + if (ret || !glamor_egl->has_image_dma_buf_export) { + return ret; + } + +#ifndef GBM_MAX_PLANES +#define GBM_MAX_PLANES 4 +#endif + + if (!eglExportDMABUFImageQueryMESA(glamor_egl->display, pixmap_priv->image, &fourcc, &num_planes, modifiers) || (num_planes > GBM_MAX_PLANES)) { + return NULL; + } + + fd_modifier_data = (struct gbm_import_fd_modifier_data) { + .width = pixmap->drawable.width, + .height = pixmap->drawable.height, + .format = fourcc, /* GBM and DRM formats are the same */ + .num_fds = num_planes, + .modifier = modifiers[0], + .fds = {-1, -1, -1, -1}, + .strides = {0}, + .offsets = {0}, + }; + + if (eglExportDMABUFImageMESA(glamor_egl->display, pixmap_priv->image, + fd_modifier_data.fds, + fd_modifier_data.strides, + fd_modifier_data.offsets)) { + ret = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, + &fd_modifier_data, 0); + } + for (int i = 0; i < num_planes; i++) { + if (fd_modifier_data.fds[i] >= 0) { + close(fd_modifier_data.fds[i]); + } + } +#endif + return ret; } struct gbm_bo * @@ -518,7 +450,7 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, uint32_t *strides, uint32_t *offsets, uint64_t *modifier) { -#ifdef GLAMOR_HAS_GBM +#ifdef HAVE_GBM struct gbm_bo *bo; int num_fds; #ifdef GBM_BO_WITH_MODIFIERS @@ -586,7 +518,7 @@ int glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) { -#ifdef GLAMOR_HAS_GBM +#ifdef HAVE_GBM struct gbm_bo *bo; int fd; @@ -686,8 +618,7 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap, import_data.width = width; import_data.height = height; import_data.stride = stride; - bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, - GBM_BO_USE_RENDERING); + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, 0); if (!bo) return FALSE; @@ -733,8 +664,7 @@ glamor_pixmap_from_fds(ScreenPtr screen, import_data.strides[i] = strides[i]; import_data.offsets[i] = offsets[i]; } - bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, - GBM_BO_USE_RENDERING); + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0); if (bo) { screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, TRUE); @@ -751,7 +681,7 @@ glamor_pixmap_from_fds(ScreenPtr screen, error: if (ret == FALSE) { - dixDestroyPixmap(pixmap, 0); + screen->DestroyPixmap(pixmap); return NULL; } return pixmap; @@ -773,7 +703,7 @@ glamor_pixmap_from_fd(ScreenPtr screen, stride, depth, bpp); if (ret == FALSE) { - dixDestroyPixmap(pixmap, 0); + screen->DestroyPixmap(pixmap); return NULL; } return pixmap; @@ -786,12 +716,10 @@ glamor_get_formats(ScreenPtr screen, #ifdef GLAMOR_HAS_EGL_QUERY_DMABUF struct glamor_egl_screen_private *glamor_egl; EGLint num; -#endif - /* Explicitly zero the count and formats as the caller may ignore the return value */ + /* Explicitly zero the count as the caller may ignore the return value */ *num_formats = 0; - *formats = NULL; -#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); if (!glamor_egl->dmabuf_capable) @@ -810,13 +738,15 @@ glamor_get_formats(ScreenPtr screen, if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num, (EGLint *) *formats, &num)) { free(*formats); - *formats = NULL; return FALSE; } *num_formats = num; -#endif return TRUE; +#else + *num_formats = 0; + return TRUE; +#endif } Bool @@ -826,12 +756,10 @@ glamor_get_modifiers(ScreenPtr screen, uint32_t format, #ifdef GLAMOR_HAS_EGL_QUERY_DMABUF struct glamor_egl_screen_private *glamor_egl; EGLint num; -#endif - /* Explicitly zero the count and modifiers as the caller may ignore the return value */ + /* Explicitly zero the count as the caller may ignore the return value */ *num_modifiers = 0; - *modifiers = NULL; -#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); if (!glamor_egl->dmabuf_capable) @@ -856,8 +784,11 @@ glamor_get_modifiers(ScreenPtr screen, uint32_t format, } *num_modifiers = num; -#endif return TRUE; +#else + *num_modifiers = 0; + return TRUE; +#endif } const char * @@ -875,20 +806,30 @@ glamor_egl_get_driver_name(ScreenPtr screen) return NULL; } -static void glamor_egl_pixmap_destroy(CallbackListPtr *pcbl, ScreenPtr pScreen, PixmapPtr pixmap) + +static Bool +glamor_egl_destroy_pixmap(PixmapPtr pixmap) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); + Bool ret; - struct glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); + if (pixmap->refcnt == 1) { + struct glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); - BUG_RETURN(!pixmap_priv); + if (pixmap_priv->image) + eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image); + } - if (pixmap_priv->image) - eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image); + screen->DestroyPixmap = glamor_egl->saved_destroy_pixmap; + ret = screen->DestroyPixmap(pixmap); + glamor_egl->saved_destroy_pixmap = screen->DestroyPixmap; + screen->DestroyPixmap = glamor_egl_destroy_pixmap; + + return ret; } void @@ -905,10 +846,8 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) temp_img = back_priv->image; temp_mod = back_priv->used_modifiers; - BUG_RETURN(!back_priv); back_priv->image = front_priv->image; back_priv->used_modifiers = front_priv->used_modifiers; - BUG_RETURN(!front_priv); front_priv->image = temp_img; front_priv->used_modifiers = temp_mod; @@ -916,7 +855,8 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); } -static void glamor_egl_close_screen(CallbackListPtr *pcbl, ScreenPtr screen, void *unused) +static Bool +glamor_egl_close_screen(ScreenPtr screen) { ScrnInfoPtr scrn; struct glamor_egl_screen_private *glamor_egl; @@ -926,15 +866,14 @@ static void glamor_egl_close_screen(CallbackListPtr *pcbl, ScreenPtr screen, voi scrn = xf86ScreenToScrn(screen); glamor_egl = glamor_egl_get_screen_private(scrn); screen_pixmap = screen->GetScreenPixmap(screen); - pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - BUG_RETURN(!pixmap_priv); eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image); pixmap_priv->image = NULL; - dixScreenUnhookClose(screen, glamor_egl_close_screen); - dixScreenUnhookPixmapDestroy(screen, glamor_egl_pixmap_destroy); + screen->CloseScreen = glamor_egl->saved_close_screen; + + return screen->CloseScreen(screen); } #ifdef DRI3 @@ -1014,8 +953,11 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) #endif const char *gbm_backend_name; - dixScreenHookClose(screen, glamor_egl_close_screen); - dixScreenHookPixmapDestroy(screen, glamor_egl_pixmap_destroy); + glamor_egl->saved_close_screen = screen->CloseScreen; + screen->CloseScreen = glamor_egl_close_screen; + + glamor_egl->saved_destroy_pixmap = screen->DestroyPixmap; + screen->DestroyPixmap = glamor_egl_destroy_pixmap; glamor_ctx->ctx = glamor_egl->context; glamor_ctx->display = glamor_egl->display; @@ -1059,6 +1001,7 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) #ifdef GLXEXT if (!vendor_initialized) { GlxPushProvider(&glamor_provider); + xorgGlxCreateVendor(); vendor_initialized = TRUE; } #endif @@ -1154,7 +1097,7 @@ glamor_egl_try_gles_api(ScrnInfoPtr scrn) { struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); - + static const EGLint config_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE @@ -1216,12 +1159,9 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) memcpy(options, GlamorEGLOptions, sizeof(GlamorEGLOptions)); xf86ProcessOptions(scrn->scrnIndex, scrn->options, options); glvnd_vendor = xf86GetOptValString(options, GLAMOREGLOPT_VENDOR_LIBRARY); - if (glvnd_vendor) { - glamor_egl->glvnd_vendor = strdup(glvnd_vendor); - if (!glamor_egl->glvnd_vendor) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Couldn't set gl vendor to: %s\n", glvnd_vendor); - } - } + if (glvnd_vendor) + glamor_egl->glvnd_vendor = XNFstrdup(glvnd_vendor); + api = xf86GetOptValString(options, GLAMOREGLOPT_RENDERING_API); if (api && !strncasecmp(api, "es", 2)) force_es = TRUE; @@ -1250,6 +1190,10 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) goto error; } +#ifdef EGL_MESA_image_dma_buf_export + glamor_egl->has_image_dma_buf_export = epoxy_has_egl_extension(glamor_egl->display, "EGL_MESA_image_dma_buf_export"); +#endif + #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT)) { \ ErrorF("EGL_" #EXT " required.\n"); \ @@ -1331,7 +1275,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) glamor_egl->dmabuf_capable = TRUE; else if (strstr((const char *)renderer, "zink")) glamor_egl->dmabuf_capable = TRUE; - else if (strstr((const char *)renderer, "NVIDIA")) + else if (strstr((const char *)renderer, "radeonsi")) glamor_egl->dmabuf_capable = TRUE; else glamor_egl->dmabuf_capable = FALSE;