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);
}
{
/* 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;
+}
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
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);
#ifdef GLAMOR_HAS_GBM
#include <gbm.h>
+#include <drm_fourcc.h>
#endif
#if GLAMOR_GLES2
void *glamor_context;
void *current_context;
int gl_context_depth;
+ int dri3_capable;
PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr;
PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr;
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)
{
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)
{
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");
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,
screen->myNum);
return FALSE;
}
+ if (glamor_egl->dri3_capable)
+ glamor_enable_dri3(screen);
return TRUE;
}
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;
}
int state;
unsigned int render_idle_cnt;
ScreenPtr screen;
+ int dri3_enabled;
/* xv */
GLint xv_prog;