[Nouveau] [PATCH (nouveau)] Add xwayland support
Emil Velikov
emil.l.velikov at gmail.com
Sat May 26 02:50:33 PDT 2012
On Wed, 23 May 2012 13:08:08 +0100, Christopher James Halse Rogers
<christopher.halse.rogers at canonical.com> wrote:
> Signed-off-by: Christopher James Halse Rogers
> <christopher.halse.rogers at canonical.com>
> ---
> This is mostly just for testing, although it should be safe to apply to
> nouveau
> trunk.
Hi Chris
Thanks for the patch although it does not build on my system.
Comments inline
>
> src/nouveau_dri2.c | 34 +++++++++++
> src/nv_driver.c | 163
> +++++++++++++++++++++++++++++++++++++++++++++++-----
> src/nv_type.h | 7 +++
> 3 files changed, 191 insertions(+), 13 deletions(-)
>
> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
> index 7e47575..cb1a395 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 {
> @@ -660,6 +664,32 @@ nouveau_dri2_flip_event_handler(unsigned int frame,
> unsigned int tv_sec,
> free(flip);
> }
> +#ifdef XORG_WAYLAND
> +static int nouveau_auth_magic(int fd, uint32_t magic)
> +{
> + ScrnInfoPtr pScrn;
> + NVPtr pNv;
> + int i;
> +
> + /* Not wayland, go stragight to drm */
> + if (!xorgWayland)
> + return drmAuthMagic(fd, magic);
> +
> + /* Technically this should actually iterate over xf86Screens.
> + Since direct access to xf86Screens is going away, though,
> + we don't bother right now */
> + for (i = 0; i < 1; i++) {
> + pScrn = xf86Screens[i];
> + pNv = NVPTR(pScrn);
> + if (xwl_screen_get_drm_fd(pNv->xwl_screen) == fd)
> + break;
> + }
> +
> + /* Forward the request to our host */
> + return xwl_drm_authenticate(pNv->xwl_screen, magic);
> +}
> +#endif
> +
> Bool
> nouveau_dri2_init(ScreenPtr pScreen)
> {
> @@ -689,6 +719,10 @@ nouveau_dri2_init(ScreenPtr pScreen)
> dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait;
> dri2.GetMSC = nouveau_dri2_get_msc;
> +#if DRI2INFOREC_VERSION >= 5 && 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 9f6d75f..79c5c39 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.
> @@ -73,6 +77,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
> @@ -89,7 +115,7 @@ _X_EXPORT DriverRec NV = {
> NVAvailableOptions,
> NULL,
> 0,
> - NULL,
> + nouveau_driver_func,
> nouveau_device_match,
> NVPciProbe
> };
> @@ -215,7 +241,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;
> @@ -229,6 +276,17 @@ NVPciProbe(DriverPtr drv, int entity_num, struct
> pci_device *pci_dev,
> return FALSE;
> }
> + ret = drmCheckModesettingSupported(busid);
> + if (ret) {
> + xf86DrvMsg(-1, X_ERROR, "[drm] KMS not enabled\n");
> + return FALSE;
> + }
> + free(busid);
Consider moving the free() before the conditional, or it will leak memory
> +
> +#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
> @@ -243,13 +301,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:
> @@ -266,14 +317,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;
> @@ -288,6 +346,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);
> @@ -376,6 +438,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
> @@ -399,6 +466,11 @@ NVBlockHandler (
> 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
> @@ -413,6 +485,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(pScrn->scrnIndex, 0))
> return FALSE;
> @@ -425,6 +502,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
> @@ -439,6 +537,11 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen)
> ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
> 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)
> @@ -507,6 +610,11 @@ NVFreeScreen(int scrnIndex, int flags)
> if (!pNv)
> return;
> +#ifdef XORG_WAYLAND
> + if (pNv->xwl_screen)
> + xwl_screen_destroy(pNv->xwl_screen);
> +#endif
> +
> NVCloseDRM(pScrn);
> free(pScrn->driverPrivate);
> @@ -568,10 +676,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");
> @@ -582,8 +696,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");
> @@ -594,7 +713,7 @@ NVPreInitDRM(ScrnInfoPtr pScrn)
> if (ret)
> return FALSE;
> - pNv->drm_device_name = drmGetDeviceNameFromFd(DRIMasterFD(pScrn));
> + pNv->drm_device_name = drmGetDeviceNameFromFd(drm_fd);
> return TRUE;
> }
> @@ -610,6 +729,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]);
> @@ -643,6 +765,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
> if (!(pScrn->driverPrivate = xnfcalloc(1, sizeof(NVRec))))
> 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]);
> @@ -780,6 +906,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;
> @@ -887,8 +1021,8 @@ 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);
> - ret = drmmode_pre_init(pScrn, pNv->dev->fd, pScrn->bitsPerPixel >> 3);
> - if (ret == FALSE)
> + if (!xwl_screen &&
xwl_screen is undefined on a non wayland build, resulting build failure
Regards
Emil
> + !drmmode_pre_init(pScrn, pNv->dev->fd, pScrn->bitsPerPixel >> 3))
> NVPreInitFail("Kernel modesetting failed to initialize\n");
> /*
> @@ -1267,6 +1401,9 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int
> argc, char **argv)
> 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 49150ba..4e36b7f 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;
More information about the Nouveau
mailing list