[PATCH] Add xwayland support (v2)
Christopher James Halse Rogers
christopher.halse.rogers at canonical.com
Fri Jun 15 02:03:22 PDT 2012
v2: Fix build against Xservers without Wayland support
Don't try to acquire/drop drm master under Wayland
Refresh for xserver 1.13 kill-all-direct-access-to-xf86Screens
Signed-off-by: Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>
---
I'll send this upstream to nouveau once the corresponding DRI2 commit
lands; before that lands, this is broken.
src/nouveau_dri2.c | 23 +++++++
src/nv_driver.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++----
src/nv_type.h | 7 ++
3 files changed, 203 insertions(+), 11 deletions(-)
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 0b3cc38..2641bd6 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -8,6 +8,10 @@
#ifdef DRI2
#include "dri2.h"
#endif
+#ifdef XORG_WAYLAND
+#include <xf86Priv.h>
+#include <xwayland.h>
+#endif
#if defined(DRI2) && DRI2INFOREC_VERSION >= 3
struct nouveau_dri2_buffer {
@@ -653,6 +657,21 @@ nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
free(flip);
}
+#ifdef XORG_WAYLAND
+static int nouveau_auth_magic(ScreenPtr pScreen, int fd, uint32_t magic)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+
+ /* Not wayland, go stragight to drm */
+ if (!xorgWayland)
+ return drmAuthMagic(fd, magic);
+
+ /* Forward the request to our host */
+ return xwl_drm_authenticate(pNv->xwl_screen, magic);
+}
+#endif
+
Bool
nouveau_dri2_init(ScreenPtr pScreen)
{
@@ -682,6 +701,10 @@ nouveau_dri2_init(ScreenPtr pScreen)
dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait;
dri2.GetMSC = nouveau_dri2_get_msc;
+#if DRI2INFOREC_VERSION >= 7 && defined(XORG_WAYLAND)
+ dri2.AuthMagic = nouveau_auth_magic;
+#endif
+
#if DRI2INFOREC_VERSION >= 6
dri2.SwapLimitValidate = nouveau_dri2_swap_limit_validate;
#endif
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 9a7b9c2..04409f2 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -32,6 +32,10 @@
#ifdef DRI2
#include "dri2.h"
#endif
+#ifdef XORG_WAYLAND
+#include <xf86Priv.h>
+#include <xwayland.h>
+#endif
/*
* Forward definitions for the functions that make up the driver.
@@ -72,6 +76,28 @@ static Bool NVPciProbe ( DriverPtr drv,
struct pci_device *dev,
intptr_t match_data );
+
+static Bool nouveau_driver_func(ScrnInfoPtr pScrn,
+ xorgDriverFuncOp op,
+ pointer ptr)
+{
+ xorgHWFlags *flag;
+
+ switch (op) {
+ case GET_REQUIRED_HW_INTERFACES:
+ flag = (CARD32*)ptr;
+ (*flag) = 0;
+#ifdef XORG_WAYLAND
+ if (xorgWayland)
+ (*flag) = HW_SKIP_CONSOLE;
+#endif
+ return TRUE;
+ default:
+ /* Unknown or deprecated function */
+ return FALSE;
+ }
+}
+
/*
* This contains the functions needed by the server after loading the
* driver module. It must be supplied, and gets added the driver list by
@@ -88,7 +114,7 @@ _X_EXPORT DriverRec NV = {
NVAvailableOptions,
NULL,
0,
- NULL,
+ nouveau_driver_func,
nouveau_device_match,
NVPciProbe
};
@@ -214,7 +240,28 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
drmVersion *version;
int chipset, ret;
char *busid;
+#ifdef XORG_WAYLAND
+ struct xwl_screen *xwl_screen = NULL;
+ if (xorgWayland) {
+ xwl_screen = xwl_screen_create ();
+ if (!xwl_screen) {
+ xf86DrvMsg(-1, X_ERROR, "Failed to initialise xwayland.\n");
+ return FALSE;
+ }
+ if (xwl_drm_pre_init(xwl_screen) != Success) {
+ xwl_screen_destroy(xwl_screen);
+ xf86DrvMsg(-1, X_ERROR, "Failed to initialise xwayland drm.\n");
+ return FALSE;
+ }
+ ret = nouveau_device_wrap(xwl_screen_get_drm_fd(xwl_screen), 0, &dev);
+ if (ret) {
+ xwl_screen_destroy(xwl_screen);
+ xf86DrvMsg(-1, X_ERROR, "[drm] Failed to create drm device.\n");
+ return FALSE;
+ }
+ } else {
+#endif
if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
xf86DrvMsg(-1, X_ERROR, "[drm] No DRICreatePCIBusID symbol\n");
return FALSE;
@@ -228,6 +275,17 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
return FALSE;
}
+ ret = drmCheckModesettingSupported(busid);
+ free(busid);
+
+ if (ret) {
+ xf86DrvMsg(-1, X_ERROR, "[drm] KMS not enabled\n");
+ return FALSE;
+ }
+#ifdef XORG_WAYLAND
+ }
+#endif
+
/* Check the version reported by the kernel module. In theory we
* shouldn't have to do this, as libdrm_nouveau will do its own checks.
* But, we're currently using the kernel patchlevel to also version
@@ -242,13 +300,6 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
chipset = dev->chipset;
nouveau_device_del(&dev);
- ret = drmCheckModesettingSupported(busid);
- free(busid);
- if (ret) {
- xf86DrvMsg(-1, X_ERROR, "[drm] KMS not enabled\n");
- return FALSE;
- }
-
switch (chipset & 0xf0) {
case 0x00:
case 0x10:
@@ -265,14 +316,21 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
case 0xe0:
break;
default:
+#ifdef XORG_WAYLAND
+ xwl_screen_destroy(xwl_screen);
+#endif
xf86DrvMsg(-1, X_ERROR, "Unknown chipset: NV%02x\n", chipset);
return FALSE;
}
pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NVChipsets,
NULL, NULL, NULL, NULL, NULL);
- if (!pScrn)
+ if (!pScrn) {
+#ifdef XORG_WAYLAND
+ xwl_screen_destroy(xwl_screen);
+#endif
return FALSE;
+ }
pScrn->driverVersion = NV_VERSION;
pScrn->driverName = NV_DRIVER_NAME;
@@ -287,6 +345,10 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
pScrn->LeaveVT = NVLeaveVT;
pScrn->FreeScreen = NVFreeScreen;
+#ifdef XORG_WAYLAND
+ pScrn->driverPrivate = xwl_screen;
+#endif
+
xf86SetEntitySharable(entity_num);
pEnt = xf86GetEntityInfo(entity_num);
@@ -333,7 +395,15 @@ NVEnterVT(VT_FUNC_ARGS_DECL)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVEnterVT is called.\n");
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen) {
+ ret = FALSE;
+ } else {
+#endif
ret = drmSetMaster(pNv->dev->fd);
+#ifdef XORG_WAYLAND
+ }
+#endif
if (ret)
ErrorF("Unable to get master: %s\n", strerror(errno));
@@ -361,7 +431,15 @@ NVLeaveVT(VT_FUNC_ARGS_DECL)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVLeaveVT is called.\n");
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen) {
+ ret = FALSE;
+ } else {
+#endif
ret = drmDropMaster(pNv->dev->fd);
+#ifdef XORG_WAYLAND
+ }
+#endif
if (ret)
ErrorF("Error dropping master: %d\n", ret);
}
@@ -374,6 +452,11 @@ NVFlushCallback(CallbackListPtr *list, pointer user_data, pointer call_data)
if (pScrn->vtSema && !pNv->NoAccel)
nouveau_pushbuf_kick(pNv->pushbuf, pNv->pushbuf->channel);
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen)
+ xwl_screen_post_damage(pNv->xwl_screen);
+#endif
+
}
static void
@@ -392,6 +475,11 @@ NVBlockHandler (BLOCKHANDLER_ARGS_DECL)
if (pNv->VideoTimerCallback)
(*pNv->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen)
+ xwl_screen_post_damage(pNv->xwl_screen);
+#endif
}
static Bool
@@ -406,6 +494,11 @@ NVCreateScreenResources(ScreenPtr pScreen)
return FALSE;
pScreen->CreateScreenResources = NVCreateScreenResources;
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen)
+ xwl_screen_init(pNv->xwl_screen, pScreen);
+#endif
+
drmmode_fbcon_copy(pScreen);
if (!NVEnterVT(VT_FUNC_ARGS(0)))
return FALSE;
@@ -418,6 +511,27 @@ NVCreateScreenResources(ScreenPtr pScreen)
return TRUE;
}
+#ifdef XORG_WAYLAND
+static int nouveau_create_window_buffer(struct xwl_window *xwl_window,
+ PixmapPtr pixmap)
+{
+ uint32_t name;
+ struct nouveau_bo *bo;
+
+ bo = nouveau_pixmap_bo(pixmap);
+ if (bo == NULL || nouveau_bo_name_get(bo, &name) != 0)
+ return BadDrawable;
+
+ return xwl_create_window_buffer_drm(xwl_window, pixmap, name);
+}
+
+static struct xwl_driver xwl_driver = {
+ .version = 1,
+ .use_drm = 1,
+ .create_window_buffer = nouveau_create_window_buffer
+};
+#endif
+
/*
* This is called at the end of each server generation. It restores the
* original (text) mode. It should also unmap the video memory, and free
@@ -432,6 +546,11 @@ NVCloseScreen(CLOSE_SCREEN_ARGS_DECL)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
NVPtr pNv = NVPTR(pScrn);
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen)
+ xwl_screen_close(pNv->xwl_screen);
+#endif
+
drmmode_screen_fini(pScreen);
if (!pNv->NoAccel)
@@ -499,6 +618,11 @@ NVFreeScreen(FREE_SCREEN_ARGS_DECL)
if (!pNv)
return;
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen)
+ xwl_screen_destroy(pNv->xwl_screen);
+#endif
+
NVCloseDRM(pScrn);
free(pScrn->driverPrivate);
@@ -560,10 +684,16 @@ NVPreInitDRM(ScrnInfoPtr pScrn)
NVPtr pNv = NVPTR(pScrn);
char *bus_id;
int ret;
+ int drm_fd;
if (!NVDRIGetVersion(pScrn))
return FALSE;
+#ifdef XORG_WAYLAND
+ if (pNv->xwl_screen)
+ drm_fd = xwl_screen_get_drm_fd(pNv->xwl_screen);
+ else {
+#endif
/* Load the kernel module, and open the DRM */
bus_id = DRICreatePCIBusID(pNv->PciInfo);
ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, bus_id, "nouveau");
@@ -574,8 +704,13 @@ NVPreInitDRM(ScrnInfoPtr pScrn)
return FALSE;
}
+ drm_fd = DRIMasterFD(pScrn);
+#ifdef XORG_WAYLAND
+ }
+#endif
+
/* Initialise libdrm_nouveau */
- ret = nouveau_device_wrap(DRIMasterFD(pScrn), 1, &pNv->dev);
+ ret = nouveau_device_wrap(drm_fd, 1, &pNv->dev);
if (ret) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"[drm] error creating device\n");
@@ -586,7 +721,7 @@ NVPreInitDRM(ScrnInfoPtr pScrn)
if (ret)
return FALSE;
- pNv->drm_device_name = drmGetDeviceNameFromFd(DRIMasterFD(pScrn));
+ pNv->drm_device_name = drmGetDeviceNameFromFd(drm_fd);
return TRUE;
}
@@ -602,6 +737,9 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
uint64_t v;
int ret;
int defaultDepth = 0;
+#ifdef XORG_WAYLAND
+ struct xwl_screen *xwl_screen = pScrn->driverPrivate;
+#endif
if (flags & PROBE_DETECT) {
EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
@@ -636,6 +774,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
pNv = NVPTR(pScrn);
+#ifdef XORG_WAYLAND
+ pNv->xwl_screen = xwl_screen;
+#endif
+
/* Get the entity, and make sure it is PCI. */
pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pNv->pEnt->location.type != BUS_PCI)
@@ -772,6 +914,14 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
memcpy(pNv->Options, NVOptions, sizeof(NVOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options);
+#ifdef XORG_WAYLAND
+ if (xwl_screen) {
+ if (!xwl_screen_pre_init(pScrn, xwl_screen, 0, &xwl_driver)) {
+ NVPreInitFail("Failed to initialise xwayland\n");
+ }
+ }
+#endif
+
from = X_DEFAULT;
pNv->HWCursor = TRUE;
@@ -882,7 +1032,16 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, from, "Swap limit set to %d [Max allowed %d]%s\n",
pNv->swap_limit, pNv->max_swap_limit, reason);
+#ifdef XORG_WAYLAND
+ if (xwl_screen)
+ ret = TRUE;
+ else {
+#endif
ret = drmmode_pre_init(pScrn, pNv->dev->fd, pScrn->bitsPerPixel >> 3);
+#ifdef XORG_WAYLAND
+ }
+#endif
+
if (ret == FALSE)
NVPreInitFail("Kernel modesetting failed to initialize\n");
@@ -1262,6 +1421,9 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL)
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+#ifdef XORG_WAYLAND
+ if (!pNv->xwl_screen)
+#endif
drmmode_screen_init(pScreen);
return TRUE;
}
diff --git a/src/nv_type.h b/src/nv_type.h
index 02fa383..3404a6e 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -15,6 +15,9 @@
#else
#error "This driver requires a DRI-enabled X server"
#endif
+#ifdef XORG_WAYLAND
+#include <xwayland.h>
+#endif
#define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04
@@ -76,6 +79,10 @@ typedef struct _NVRec {
void *drmmode; /* for KMS */
+#ifdef XORG_WAYLAND
+ struct xwl_screen *xwl_screen;
+#endif
+
/* DRM interface */
struct nouveau_device *dev;
char *drm_device_name;
--
1.7.10.4
More information about the wayland-devel
mailing list