vfb: add DRI3/glamor support

This commit adds DRI3/glamor support, effectively translating into
hardware GPU support.

Theoretically it should be possible to use DRM/GPU drivers such as
virtio or vgem, although only the intel i915 driver is currently tested.

Since Xvfb does no modeset, it opens the render node. Currently that is
fixed to "/dev/dri/renderD128" and will be tweaked with future commits.

Specific use-cases are left for the reader - testing glamor, GL driver
or others.

v2: Drop GLAMOR_NO_XV, use GLAMOR_FOR_XORG instead (Michel Dänzer)
v3: Fix build w/o glamor
v4:
 - Split out glamor dependency patch for meson (Pekka)
 - Enhance commit message (Pekka)
 - Use O_CLOEXEC with open() (Pekka)
 - Enhance error path, memory leak comments (Pekka)

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
This commit is contained in:
Emil Velikov 2019-07-12 14:45:16 +01:00 committed by Emil Velikov
parent 9e574a5bd8
commit b2a0d6065d
3 changed files with 146 additions and 2 deletions

View File

@ -68,6 +68,14 @@ from The Open Group.
#include "glx_extinit.h"
#include "randrstr.h"
#ifdef GLAMOR_HAS_GBM
#include <glamor.h>
#include <gbm.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#define VFB_DEFAULT_WIDTH 1280
#define VFB_DEFAULT_HEIGHT 1024
#define VFB_DEFAULT_DEPTH 24
@ -101,6 +109,12 @@ typedef struct {
#ifdef HAS_SHM
int shmid;
#endif
#ifdef GLAMOR_HAS_GBM
int fd;
CreateScreenResourcesProcPtr createScreenResources;
struct gbm_device *gbm;
struct gbm_bo *front_bo;
#endif
} vfbScreenInfo, *vfbScreenInfoPtr;
static int vfbNumScreens;
@ -726,10 +740,110 @@ vfbCloseScreen(ScreenPtr pScreen)
if (pScreen->devPrivate)
(*pScreen->DestroyPixmap) (pScreen->devPrivate);
pScreen->devPrivate = NULL;
#ifdef GLAMOR_HAS_GBM
if (pvfb->fd >= 0) {
if (pvfb->front_bo) {
gbm_bo_destroy(pvfb->front_bo);
pvfb->front_bo = NULL;
}
close(pvfb->fd);
pvfb->fd = -1;
}
#endif
/*
* XXX: There is an existing vfbScreens leak. Should we free() it directly
* or otherwise - input welcome.
*/
return pScreen->CloseScreen(pScreen);
}
#ifdef GLAMOR_HAS_GBM
static Bool
vfbCreateScreenResources(ScreenPtr pScreen)
{
vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
PixmapPtr pixmap;
Bool ret;
pScreen->CreateScreenResources = pvfb->createScreenResources;
ret = pScreen->CreateScreenResources(pScreen);
pScreen->CreateScreenResources = vfbCreateScreenResources;
if (!ret)
return FALSE;
pixmap = pScreen->GetScreenPixmap(pScreen);
/* TODO: add support for modifiers at some point */
if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, pvfb->front_bo,
FALSE)) {
LogMessage(X_ERROR, "glamor_egl_create_textured_pixmap() failed\n");
/* TODO: plug the leak, aka undo the CreateScreenResources() call above. */
return FALSE;
}
return TRUE;
}
static void
vfbDRIInit(ScreenPtr pScreen)
{
vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
/* TODO: don't hardcode the node name */
const char *node_name = "/dev/dri/renderD128";
const char *error_msg;
pvfb->fd = open(node_name, O_RDWR | O_CLOEXEC);
if (pvfb->fd < 0) {
error_msg = "Failed to open device node";
goto out;
}
if (!glamor_egl_init(pScreen, pvfb->fd)) {
error_msg = "Failed to initialize glamor";
goto close_fd;
}
pvfb->gbm = glamor_egl_get_gbm_device(pScreen);
if (!pvfb->gbm) {
error_msg = "Failed to get gbm device";
goto egl_fini;
}
pvfb->front_bo = gbm_bo_create(pvfb->gbm,
pScreen->width, pScreen->height,
GBM_FORMAT_ARGB8888,
GBM_BO_USE_RENDERING);
if (!pvfb->front_bo) {
error_msg = "Failed to create front buffer";
goto egl_fini;
}
if (!glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN)) {
error_msg = "Failed to initialize glamor at ScreenInit() time";
goto destroy_bo;
}
pvfb->createScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = vfbCreateScreenResources;
return;
destroy_bo:
gbm_bo_destroy(pvfb->front_bo);
egl_fini:
/* TODO: There's no glamor_egl_fini just yet */
close_fd:
close(pvfb->fd);
out:
LogMessage(X_ERROR, "%s. Disabling GLAMOR/DRI3.\n", error_msg);
return;
}
#else
static void
vfbDRIInit(ScreenPtr pScreen)
{
}
#endif
static Bool
vfbRROutputValidateMode(ScreenPtr pScreen,
RROutputPtr output,
@ -925,8 +1039,10 @@ vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!ret)
return FALSE;
if (Render)
if (Render) {
fbPictureInit(pScreen, 0, 0);
vfbDRIInit(pScreen);
}
if (!vfbRandRInit(pScreen))
return FALSE;

View File

@ -4,6 +4,10 @@ bin_PROGRAMS = Xvfb
AM_CFLAGS = -DHAVE_DIX_CONFIG_H \
$(XVFBMODULES_CFLAGS) \
-I$(top_srcdir)/glamor/ \
-I$(top_srcdir)/dri3/ \
$(LIBDRM_CFLAGS) \
$(GBM_CFLAGS) \
$(DIX_CFLAGS)
SRCS = InitInput.c \
@ -13,6 +17,7 @@ SRCS = InitInput.c \
Xvfb_SOURCES = $(SRCS)
XVFB_LIBS = \
$(glamor_lib) \
@XVFB_LIBS@ \
$(MAIN_LIB) \
$(XSERVER_LIBS) \
@ -22,5 +27,13 @@ Xvfb_LDADD = $(XVFB_LIBS) $(XVFB_SYS_LIBS) $(XSERVER_SYS_LIBS)
Xvfb_DEPENDENCIES = $(XVFB_LIBS)
Xvfb_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
if GLAMOR_EGL
Xvfb_SOURCES += $(top_srcdir)/glamor/glamor_egl.c
glamor_lib = $(top_builddir)/glamor/libglamor.la
Xvfb_LDADD += $(GLAMOR_LIBS) $(GBM_LIBS) $(LIBDRM_LIBS) -lEGL -lGL
Xvfb_DEPENDENCIES = $(glamor_lib) $(XVFB_LIBS)
endif
relink:
$(AM_V_at)rm -f Xvfb$(EXEEXT) && $(MAKE) Xvfb$(EXEEXT)

View File

@ -4,12 +4,27 @@ srcs = [
'../../mi/miinitext.c',
]
vfb_dep = []
vfb_glamor = []
if build_glamor
srcs += '../../glamor/glamor_egl.c'
vfb_dep += [
libdrm_dep,
gbm_dep,
]
vfb_glamor += glamor
endif
xvfb_server = executable(
'Xvfb',
srcs,
include_directories: inc,
dependencies: common_dep,
dependencies: [
common_dep,
vfb_dep,
],
link_with: [
vfb_glamor,
libxserver_main,
libxserver_fb,
libxserver,