diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c index f6079fefe..56795db19 100644 --- a/hw/vfb/InitOutput.c +++ b/hw/vfb/InitOutput.c @@ -68,6 +68,14 @@ from The Open Group. #include "glx_extinit.h" #include "randrstr.h" +#ifdef GLAMOR_HAS_GBM +#include +#include + +#include +#include +#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; diff --git a/hw/vfb/Makefile.am b/hw/vfb/Makefile.am index 70333976c..d3d076d00 100644 --- a/hw/vfb/Makefile.am +++ b/hw/vfb/Makefile.am @@ -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) diff --git a/hw/vfb/meson.build b/hw/vfb/meson.build index 537e96a72..3cfd4fe59 100644 --- a/hw/vfb/meson.build +++ b/hw/vfb/meson.build @@ -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,