[Glamor] [PATCH v3] Add DRI3 support to glamor
zhigang gong
zhigang.gong at gmail.com
Fri Dec 6 08:00:39 PST 2013
LGTM, pushed, thanks for your contribution.
On Thu, Dec 5, 2013 at 3:49 PM, Axel Davy <axel.davy at ens.fr> wrote:
> This implements some DRI3 helpers to help the DDXs using
> glamor to support DRI3.
>
> Signed-off-by: Axel Davy <axel.davy at ens.fr>
> ---
> v3: fix whitespace errors of v2
>
> configure.ac | 13 ++++
> src/glamor.c | 76 +++++++++++++++++-
> src/glamor.h | 68 ++++++++++++++++-
> src/glamor_egl.c | 225
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/glamor_fbo.c | 36 ++++++---
> src/glamor_priv.h | 1 +
> 6 files changed, 405 insertions(+), 14 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index b7b25d0..21bc794 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -134,6 +134,19 @@ if test "x$EGL = xyes"; then
> fi
> fi
>
> +AC_MSG_CHECKING([Enable Glamor Dri3 helpers])
> +AC_ARG_ENABLE(glamor-dri3, AS_HELP_STRING([--enable-glamor-dri3], [Build
> glamor Dri3 helpers (default: yes if gbm is detected)]),
> [GLAMOR_DRI3_HELPERS="$enableval"], [GLAMOR_DRI3_HELPERS=yes])
> +
> +if test "x$GLAMOR_DRI3_HELPERS" = xyes -a "x$GLAMOR_HAS_GBM" = xno; then
> + GLAMOR_DRI3_HELPERS=no
> +fi
> +
> +AC_MSG_RESULT([$GLAMOR_DRI3_HELPERS])
> +
> +if test "x$GLAMOR_DRI3_HELPERS" = xyes; then
> + AC_DEFINE(GLAMOR_HAS_DRI3_SUPPORT, 1, [Enable Dri3 helpers])
> +fi
> +
> dnl
> dnl TLS detection
> dnl
> diff --git a/src/glamor.c b/src/glamor.c
> index e8e68be..93d3c5e 100644
> --- a/src/glamor.c
> +++ b/src/glamor.c
> @@ -209,7 +209,12 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap)
> Bool
> glamor_destroy_pixmap(PixmapPtr pixmap)
> {
> - glamor_destroy_textured_pixmap(pixmap);
> + glamor_screen_private
> + *glamor_priv =
> glamor_get_screen_private(pixmap->drawable.pScreen);
> + if (glamor_priv->dri3_enabled)
> + glamor_egl_destroy_textured_pixmap(pixmap);
> + else
> + glamor_destroy_textured_pixmap(pixmap);
> return fbDestroyPixmap(pixmap);
> }
>
> @@ -552,3 +557,72 @@ glamor_fini(ScreenPtr screen)
> {
> /* Do nothing currently. */
> }
> +
> +void glamor_enable_dri3(ScreenPtr screen)
> +{
> + glamor_screen_private *glamor_priv =
> + glamor_get_screen_private(screen);
> + glamor_priv->dri3_enabled = TRUE;
> +}
> +
> +Bool glamor_is_dri3_support_enabled(ScreenPtr screen)
> +{
> + glamor_screen_private *glamor_priv =
> + glamor_get_screen_private(screen);
> + return glamor_priv->dri3_enabled;
> +}
> +
> +int
> +glamor_dri3_fd_from_pixmap (ScreenPtr screen,
> + PixmapPtr pixmap,
> + CARD16 *stride,
> + CARD32 *size)
> +{
> + glamor_pixmap_private *pixmap_priv;
> + glamor_screen_private *glamor_priv =
> + glamor_get_screen_private(pixmap->drawable.pScreen);
> +
> + pixmap_priv = glamor_get_pixmap_private(pixmap);
> + if (pixmap_priv == NULL || !glamor_priv->dri3_enabled)
> + return -1;
> + switch (pixmap_priv->type)
> + {
> + case GLAMOR_TEXTURE_DRM:
> + case GLAMOR_TEXTURE_ONLY:
> + glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0);
> + return glamor_egl_dri3_fd_name_from_tex(screen,
> + pixmap,
> +
> pixmap_priv->base.fbo->tex,
> + FALSE,
> + stride,
> + size);
> + default: break;
> + }
> + return -1;
> +}
> +
> +int
> +glamor_dri3_name_from_pixmap (PixmapPtr pixmap)
> +{
> + glamor_pixmap_private *pixmap_priv;
> + glamor_screen_private *glamor_priv =
> + glamor_get_screen_private(pixmap->drawable.pScreen);
> +
> + pixmap_priv = glamor_get_pixmap_private(pixmap);
> + if (pixmap_priv == NULL || !glamor_priv->dri3_enabled)
> + return -1;
> + switch (pixmap_priv->type)
> + {
> + case GLAMOR_TEXTURE_DRM:
> + case GLAMOR_TEXTURE_ONLY:
> + glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0);
> + return
> glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen,
> + pixmap,
> +
> pixmap_priv->base.fbo->tex,
> + TRUE,
> + NULL,
> + NULL);
> + default: break;
> + }
> + return -1;
> +}
> diff --git a/src/glamor.h b/src/glamor.h
> index 927892f..1bb48ed 100644
> --- a/src/glamor.h
> +++ b/src/glamor.h
> @@ -164,6 +164,71 @@ extern _X_EXPORT void
> glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr bac
>
> extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front,
> PixmapPtr back);
>
> +/* The DDX is not supposed to call these three functions */
> +extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen);
> +extern _X_EXPORT unsigned int
> glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h);
> +extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr,
> PixmapPtr, unsigned int, Bool, CARD16*, CARD32*);
> +
> +/* @glamor_is_dri3_support_enabled: Returns if DRI3 support is enabled.
> + *
> + * @screen: Current screen pointer.
> + *
> + * To have DRI3 support enabled, glamor and glamor_egl need to be
> initialized,
> + * and glamor_egl_init_textured_pixmap need to be called. glamor also
> + * has to be compiled with gbm support.
> + * The EGL layer need to have the following extensions working:
> + * .EGL_KHR_gl_texture_2D_image
> + * .EGL_EXT_image_dma_buf_import
> + * If DRI3 support is not enabled, the following helpers will return an
> error.
> + * */
> +extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
> +
> +/* @glamor_dri3_fd_from_pixmap: DRI3 helper to get a dma-buf fd from a
> pixmap.
> + *
> + * @screen: Current screen pointer.
> + * @pixmap: The pixmap from which we want the fd.
> + * @stride, @size: Pointers to fill the stride and size of the
> + * buffer associated to the fd.
> + *
> + * the pixmap and the buffer associated by the fd will share the same
> + * content.
> + * Returns the fd on success, -1 on error.
> + * */
> +extern _X_EXPORT int glamor_dri3_fd_from_pixmap (ScreenPtr screen,
> + PixmapPtr pixmap,
> + CARD16 *stride,
> + CARD32 *size);
> +
> +/* @glamor_dri3_name_from_pixmap: helper to get an gem name from a pixmap.
> + *
> + * @pixmap: The pixmap from which we want the gem name.
> + *
> + * the pixmap and the buffer associated by the gem name will share the
> same
> + * content. This function can be used by the DDX to support DRI2, but
> needs
> + * glamor DRI3 support to be activated.
> + * Returns the name on success, -1 on error.
> + * */
> +extern _X_EXPORT int glamor_dri3_name_from_pixmap (PixmapPtr pixmap);
> +
> +/* @glamor_egl_dri3_pixmap_from_fd: DRI3 helper to get a pixmap from a
> dma-buf fd.
> + *
> + * @screen: Current screen pointer.
> + * @fd: The dma-buf fd to import.
> + * @width: The width of the buffer.
> + * @height: The height of the buffer.
> + * @stride: The stride of the buffer.
> + * @depth: The depth of the buffer.
> + * @bpp: The number of bpp of the buffer.
> + *
> + * Returns a valid pixmap if the import succeeded, else NULL.
> + * */
> +extern _X_EXPORT PixmapPtr glamor_egl_dri3_pixmap_from_fd (ScreenPtr
> screen,
> + int fd,
> + CARD16 width,
> + CARD16 height,
> + CARD16 stride,
> + CARD8 depth,
> + CARD8 bpp);
>
> #ifdef GLAMOR_FOR_XORG
>
> @@ -243,9 +308,10 @@ extern _X_EXPORT Bool
> glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
> void *bo);
>
> -extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr
> pixmap);
> #endif
>
> +extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr
> pixmap);
> +
> extern _X_EXPORT int glamor_create_gc(GCPtr gc);
>
> extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes,
> DrawablePtr drawable);
> diff --git a/src/glamor_egl.c b/src/glamor_egl.c
> index 13b7f44..bf0db3a 100644
> --- a/src/glamor_egl.c
> +++ b/src/glamor_egl.c
> @@ -45,6 +45,7 @@
>
> #ifdef GLAMOR_HAS_GBM
> #include <gbm.h>
> +#include <drm_fourcc.h>
> #endif
>
> #if GLAMOR_GLES2
> @@ -95,6 +96,7 @@ struct glamor_egl_screen_private {
> void *glamor_context;
> void *current_context;
> int gl_context_depth;
> + int dri3_capable;
>
> PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr;
> PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr;
> @@ -218,6 +220,47 @@ glamor_create_texture_from_image(struct
> glamor_egl_screen_private
> return TRUE;
> }
>
> +unsigned int
> +glamor_egl_create_argb8888_based_texture(ScreenPtr screen,
> + int w,
> + int h)
> +{
> + ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> + struct glamor_egl_screen_private *glamor_egl;
> + EGLImageKHR image;
> + GLuint texture;
> +#ifdef GLAMOR_HAS_DRI3_SUPPORT
> + struct gbm_bo *bo;
> + EGLNativePixmapType native_pixmap;
> + glamor_egl = glamor_egl_get_screen_private(scrn);
> + bo = gbm_bo_create (glamor_egl->gbm, w, h, GBM_FORMAT_ARGB8888,
> + GBM_BO_USE_RENDERING |
> + GBM_BO_USE_SCANOUT);
> + if (!bo)
> + return 0;
> +
> + /* If the following assignment raises an error or a warning
> + * then that means EGLNativePixmapType is not struct gbm_bo *
> + * on your platform: This code won't work and you should not
> + * compile with dri3 support enabled */
> + native_pixmap = bo;
> +
> + image = glamor_egl->egl_create_image_khr(glamor_egl->display,
> + EGL_NO_CONTEXT,
> + EGL_NATIVE_PIXMAP_KHR,
> + native_pixmap, NULL);
> + gbm_bo_destroy(bo);
> + if (image == EGL_NO_IMAGE_KHR)
> + return 0;
> + glamor_create_texture_from_image(glamor_egl, image, &texture);
> + glamor_egl->egl_destroy_image_khr(glamor_egl->display, image);
> +
> + return texture;
> +#else
> + return 0; /* this path should never happen */
> +#endif
> +}
> +
> Bool
> glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int
> stride)
> {
> @@ -349,6 +392,178 @@ done:
> return ret;
> }
>
> +#ifdef GLAMOR_HAS_DRI3_SUPPORT
> +int glamor_get_fd_from_bo (int gbm_fd, struct gbm_bo *bo, int *fd);
> +void glamor_get_name_from_bo (int gbm_fd, struct gbm_bo *bo, int *name);
> +int
> +glamor_get_fd_from_bo (int gbm_fd, struct gbm_bo *bo, int *fd)
> +{
> + union gbm_bo_handle handle;
> + struct drm_prime_handle args;
> +
> + handle = gbm_bo_get_handle(bo);
> + args.handle = handle.u32;
> + args.flags = DRM_CLOEXEC;
> + if (ioctl (gbm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args))
> + return FALSE;
> + *fd = args.fd;
> + return TRUE;
> +}
> +
> +void
> +glamor_get_name_from_bo (int gbm_fd, struct gbm_bo *bo, int *name)
> +{
> + union gbm_bo_handle handle;
> +
> + handle = gbm_bo_get_handle(bo);
> + if (!glamor_get_flink_name(gbm_fd, handle.u32, name))
> + *name = -1;
> +}
> +#endif
> +
> +int glamor_egl_dri3_fd_name_from_tex (ScreenPtr screen,
> + PixmapPtr pixmap,
> + unsigned int tex,
> + Bool want_name,
> + CARD16 *stride,
> + CARD32 *size)
> +{
> +#ifdef GLAMOR_HAS_DRI3_SUPPORT
> + ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> + struct glamor_egl_screen_private *glamor_egl;
> + EGLImageKHR image;
> + struct gbm_bo* bo;
> + int fd = -1;
> +
> + EGLint attribs[] = {
> + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
> + EGL_GL_TEXTURE_LEVEL_KHR, 0,
> + EGL_NONE
> + };
> +
> + glamor_egl = glamor_egl_get_screen_private(scrn);
> +
> + glamor_egl_make_current(screen);
> +
> + image = dixLookupPrivate(&pixmap->devPrivates,
> + glamor_egl_pixmap_private_key);
> +
> + if (image == EGL_NO_IMAGE_KHR || image == NULL)
> + {
> + image =
> glamor_egl->egl_create_image_khr(glamor_egl->display,
> +
> glamor_egl->context,
> +
> EGL_GL_TEXTURE_2D_KHR,
> + tex, attribs);
> + if (image == EGL_NO_IMAGE_KHR)
> + goto failure;
> +
> + dixSetPrivate(&pixmap->devPrivates,
> + glamor_egl_pixmap_private_key,
> + image);
> + glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
> + }
> +
> + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE,
> image, 0);
> + if (!bo)
> + goto failure;
> +
> + pixmap->devKind = gbm_bo_get_stride(bo);
> +
> + if (want_name)
> + {
> + if (glamor_egl->has_gem)
> + glamor_get_name_from_bo(glamor_egl->fd, bo, &fd);
> + }
> + else
> + {
> + if (glamor_get_fd_from_bo(glamor_egl->fd, bo, &fd))
> + {
> + *stride = pixmap->devKind;
> + *size = pixmap->devKind * gbm_bo_get_height(bo);
> + }
> + }
> +
> + gbm_bo_destroy(bo);
> +failure:
> + glamor_egl_restore_context(screen);
> + return fd;
> +#else
> + return -1;
> +#endif
> +}
> +
> +PixmapPtr glamor_egl_dri3_pixmap_from_fd (ScreenPtr screen,
> + int fd,
> + CARD16 width,
> + CARD16 height,
> + CARD16 stride,
> + CARD8 depth,
> + CARD8 bpp)
> +{
> +#ifdef GLAMOR_HAS_DRI3_SUPPORT
> + ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> + struct glamor_egl_screen_private *glamor_egl;
> + struct gbm_bo* bo;
> + EGLImageKHR image;
> + PixmapPtr pixmap;
> + Bool ret = FALSE;
> + EGLint attribs[] = {
> + EGL_WIDTH, 0,
> + EGL_HEIGHT, 0,
> + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888,
> + EGL_DMA_BUF_PLANE0_FD_EXT, 0,
> + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
> + EGL_DMA_BUF_PLANE0_PITCH_EXT, 0,
> + EGL_NONE
> + };
> +
> + glamor_egl = glamor_egl_get_screen_private(scrn);
> +
> + if (!glamor_egl->dri3_capable)
> + return NULL;
> +
> + if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 ||
> height == 0)
> + return NULL;
> +
> + attribs[1] = width;
> + attribs[3] = height;
> + attribs[7] = fd;
> + attribs[11] = stride;
> + image = glamor_egl->egl_create_image_khr(glamor_egl->display,
> + EGL_NO_CONTEXT,
> + EGL_LINUX_DMA_BUF_EXT,
> + NULL, attribs);
> +
> + if (image == EGL_NO_IMAGE_KHR)
> + return NULL;
> +
> + /* EGL_EXT_image_dma_buf_import can impose restrictions on the
> + * usage of the image. Use gbm_bo to bypass the limitations. */
> +
> + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE,
> image, 0);
> + glamor_egl->egl_destroy_image_khr(glamor_egl->display, image);
> +
> + if (!bo)
> + return NULL;
> +
> + pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
> + screen->ModifyPixmapHeader (pixmap, width, height, 0, 0, stride,
> NULL);
> +
> + ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo);
> + gbm_bo_destroy(bo);
> +
> + if (ret)
> + return pixmap;
> + else
> + {
> + screen->DestroyPixmap(pixmap);
> + return NULL;
> + }
> +#else
> + return NULL;
> +#endif
> +}
> +
> static void
> _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap)
> {
> @@ -558,6 +773,11 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
> GLAMOR_CHECK_EGL_EXTENSIONS(KHR_surfaceless_context,
> KHR_surfaceless_opengl);
> #endif
>
> +#ifdef GLAMOR_HAS_DRI3_SUPPORT
> + if (glamor_egl_has_extension(glamor_egl,
> "EGL_KHR_gl_texture_2D_image") &&
> + glamor_egl_has_extension(glamor_egl,
> "EGL_EXT_image_dma_buf_import") )
> + glamor_egl->dri3_capable = TRUE;
> +#endif
> glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC)
> eglGetProcAddress("eglCreateImageKHR");
>
> @@ -609,6 +829,9 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
> Bool
> glamor_egl_init_textured_pixmap(ScreenPtr screen)
> {
> + ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> + struct glamor_egl_screen_private *glamor_egl =
> + glamor_egl_get_screen_private(scrn);
> if (!dixRegisterPrivateKey
> (glamor_egl_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
> LogMessage(X_WARNING,
> @@ -616,6 +839,8 @@ glamor_egl_init_textured_pixmap(ScreenPtr screen)
> screen->myNum);
> return FALSE;
> }
> + if (glamor_egl->dri3_capable)
> + glamor_enable_dri3(screen);
> return TRUE;
> }
>
> diff --git a/src/glamor_fbo.c b/src/glamor_fbo.c
> index 4838a27..d1b087e 100644
> --- a/src/glamor_fbo.c
> +++ b/src/glamor_fbo.c
> @@ -328,18 +328,30 @@ _glamor_create_tex(glamor_screen_private
> *glamor_priv,
> int w, int h, GLenum format)
> {
> glamor_gl_dispatch *dispatch;
> - unsigned int tex;
> -
> - dispatch = glamor_get_dispatch(glamor_priv);
> - dispatch->glGenTextures(1, &tex);
> - dispatch->glBindTexture(GL_TEXTURE_2D, tex);
> - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
> - GL_NEAREST);
> - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
> - GL_NEAREST);
> - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format,
> - GL_UNSIGNED_BYTE, NULL);
> - glamor_put_dispatch(glamor_priv);
> + unsigned int tex = 0;
> +
> + /* With dri3, we want to allocate ARGB8888 pixmaps only.
> + * Depending on the implementation, GL_RGBA might not
> + * give us ARGB8888. We ask glamor_egl to use get
> + * an ARGB8888 based texture for us. */
> + if (glamor_priv->dri3_enabled && format == GL_RGBA)
> + {
> + tex =
> glamor_egl_create_argb8888_based_texture(glamor_priv->screen,
> + w, h);
> + }
> + if (!tex)
> + {
> + dispatch = glamor_get_dispatch(glamor_priv);
> + dispatch->glGenTextures(1, &tex);
> + dispatch->glBindTexture(GL_TEXTURE_2D, tex);
> + dispatch->glTexParameteri(GL_TEXTURE_2D,
> GL_TEXTURE_MIN_FILTER,
> + GL_NEAREST);
> + dispatch->glTexParameteri(GL_TEXTURE_2D,
> GL_TEXTURE_MAG_FILTER,
> + GL_NEAREST);
> + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
> + format, GL_UNSIGNED_BYTE, NULL);
> + glamor_put_dispatch(glamor_priv);
> + }
> return tex;
> }
>
> diff --git a/src/glamor_priv.h b/src/glamor_priv.h
> index b6a1075..7b8f762 100644
> --- a/src/glamor_priv.h
> +++ b/src/glamor_priv.h
> @@ -305,6 +305,7 @@ typedef struct glamor_screen_private {
> int state;
> unsigned int render_idle_cnt;
> ScreenPtr screen;
> + int dri3_enabled;
>
> /* xv */
> GLint xv_prog;
> --
> 1.8.1.2
>
> _______________________________________________
> Glamor mailing list
> Glamor at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/glamor
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/glamor/attachments/20131207/7ab6b6ed/attachment-0001.html>
More information about the Glamor
mailing list