Add DRI3 support to glamor
This implements some DRI3 helpers to help the DDXs using glamor to support DRI3. Signed-off-by: Axel Davy <axel.davy@ens.fr> Reviewed-by: Zhigang Gong <zhigang.gong@linux.intel.com>
This commit is contained in:
parent
06ba3fdfd6
commit
7cfd9cc232
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
unsigned int tex = 0;
|
||||
|
||||
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);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user