glamor: Track if BO allocation used modifiers

Keep track of whether or not we fed modifiers into GBM when we allocated
a BO. We'll use this later inside Glamor, to reallocate buffer storage
if we allocate buffer storage using modifiers, and a non-modifier-aware
client requests an export of that pixmap.

This makes it possible to run a compositing manager on an old GLX/EGL
stack on top of an X server which allocates internal buffer storage
using exotic modifiers from modifier-aware GBM/EGL/KMS.

Signed-off-by: Daniel Stone <daniels@collabora.com>
Reported-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Daniel Stone 2018-04-04 16:16:34 +01:00 committed by Adam Jackson
parent 0e9504e10c
commit 1b9fa3b64c
4 changed files with 25 additions and 11 deletions

View File

@ -391,7 +391,8 @@ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap,
*/ */
extern _X_EXPORT Bool extern _X_EXPORT Bool
glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
struct gbm_bo *bo); struct gbm_bo *bo,
Bool used_modifiers);
#endif #endif

View File

@ -150,7 +150,8 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride)
} }
static void static void
glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image) glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image,
Bool used_modifiers)
{ {
struct glamor_pixmap_private *pixmap_priv = struct glamor_pixmap_private *pixmap_priv =
glamor_get_pixmap_private(pixmap); glamor_get_pixmap_private(pixmap);
@ -165,6 +166,7 @@ glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image)
eglDestroyImageKHR(glamor_egl->display, old); eglDestroyImageKHR(glamor_egl->display, old);
} }
pixmap_priv->image = image; pixmap_priv->image = image;
pixmap_priv->used_modifiers = used_modifiers;
} }
Bool Bool
@ -204,7 +206,8 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
Bool Bool
glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
struct gbm_bo *bo) struct gbm_bo *bo,
Bool used_modifiers)
{ {
ScreenPtr screen = pixmap->drawable.pScreen; ScreenPtr screen = pixmap->drawable.pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen); ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@ -229,7 +232,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
glamor_create_texture_from_image(screen, image, &texture); glamor_create_texture_from_image(screen, image, &texture);
glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
glamor_set_pixmap_texture(pixmap, texture); glamor_set_pixmap_texture(pixmap, texture);
glamor_egl_set_pixmap_image(pixmap, image); glamor_egl_set_pixmap_image(pixmap, image, used_modifiers);
ret = TRUE; ret = TRUE;
done: done:
@ -259,6 +262,7 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
unsigned height = pixmap->drawable.height; unsigned height = pixmap->drawable.height;
uint32_t format; uint32_t format;
struct gbm_bo *bo; struct gbm_bo *bo;
Bool used_modifiers = FALSE;
PixmapPtr exported; PixmapPtr exported;
GCPtr scratch_gc; GCPtr scratch_gc;
@ -286,6 +290,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height, bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height,
format, modifiers, num_modifiers); format, modifiers, num_modifiers);
if (bo)
used_modifiers = TRUE;
free(modifiers); free(modifiers);
} }
else else
@ -309,7 +315,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0); exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0);
screen->ModifyPixmapHeader(exported, width, height, 0, 0, screen->ModifyPixmapHeader(exported, width, height, 0, 0,
gbm_bo_get_stride(bo), NULL); gbm_bo_get_stride(bo), NULL);
if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo)) { if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo,
used_modifiers)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR, xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to make %dx%dx%dbpp pixmap from GBM bo\n", "Failed to make %dx%dx%dbpp pixmap from GBM bo\n",
width, height, pixmap->drawable.bitsPerPixel); width, height, pixmap->drawable.bitsPerPixel);
@ -452,7 +459,7 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap,
screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, FALSE);
gbm_bo_destroy(bo); gbm_bo_destroy(bo);
return ret; return ret;
} }
@ -509,7 +516,7 @@ glamor_pixmap_from_fds(ScreenPtr screen,
bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0); bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0);
if (bo) { if (bo) {
screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL); screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL);
ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, TRUE);
gbm_bo_destroy(bo); gbm_bo_destroy(bo);
} }
} else } else
@ -667,7 +674,8 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap)
_X_EXPORT void _X_EXPORT void
glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
{ {
EGLImageKHR temp; EGLImageKHR temp_img;
Bool temp_mod;
struct glamor_pixmap_private *front_priv = struct glamor_pixmap_private *front_priv =
glamor_get_pixmap_private(front); glamor_get_pixmap_private(front);
struct glamor_pixmap_private *back_priv = struct glamor_pixmap_private *back_priv =
@ -675,9 +683,12 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
glamor_pixmap_exchange_fbos(front, back); glamor_pixmap_exchange_fbos(front, back);
temp = back_priv->image; temp_img = back_priv->image;
temp_mod = back_priv->used_modifiers;
back_priv->image = front_priv->image; back_priv->image = front_priv->image;
front_priv->image = temp; back_priv->used_modifiers = front_priv->used_modifiers;
front_priv->image = temp_img;
front_priv->used_modifiers = temp_mod;
glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);

View File

@ -341,6 +341,7 @@ typedef struct glamor_pixmap_private {
Bool prepared; Bool prepared;
#ifdef GLAMOR_HAS_GBM #ifdef GLAMOR_HAS_GBM
EGLImageKHR image; EGLImageKHR image;
Bool used_modifiers;
#endif #endif
/** block width of this large pixmap. */ /** block width of this large pixmap. */
int block_w; int block_w;

View File

@ -2822,7 +2822,8 @@ drmmode_set_pixmap_bo(drmmode_ptr drmmode, PixmapPtr pixmap, drmmode_bo *bo)
if (!drmmode->glamor) if (!drmmode->glamor)
return TRUE; return TRUE;
if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo->gbm)) { if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo->gbm,
bo->used_modifiers)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create pixmap\n"); xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create pixmap\n");
return FALSE; return FALSE;
} }