[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-nouveau: Changes to 'debian-unstable'



 ChangeLog                                  |  195 ++
 configure.ac                               |    2 
 debian/changelog                           |    9 
 debian/patches/02-drm-nouveau-newabi.patch | 2272 +++++++++++++++++++++++++++++
 debian/patches/series                      |    1 
 src/Makefile.am                            |    4 
 src/drmmode_display.c                      |   30 
 src/nouveau_dri2.c                         |   32 
 src/nouveau_exa.c                          |   29 
 src/nouveau_local.h                        |  186 +-
 src/nouveau_wfb.c                          |    4 
 src/nouveau_xv.c                           |   69 
 src/nv04_accel.h                           |   83 +
 src/nv04_exa.c                             |  524 +++---
 src/nv04_xv_blit.c                         |  262 +--
 src/nv10_exa.c                             |  857 ++++------
 src/nv30_exa.c                             |  975 ++++++------
 src/nv30_shaders.c                         |  347 ----
 src/nv30_shaders.h                         |   72 
 src/nv30_xv_tex.c                          |  302 +--
 src/nv40_exa.c                             |  994 +++++++-----
 src/nv40_xv_tex.c                          |  293 +--
 src/nv50_accel.c                           |  670 ++++----
 src/nv50_accel.h                           |   66 
 src/nv50_exa.c                             |  895 +++++------
 src/nv50_xv.c                              |  381 +---
 src/nv_accel_common.c                      |  582 +++----
 src/nv_dma.c                               |   77 
 src/nv_dma.h                               |    4 
 src/nv_driver.c                            |   43 
 src/nv_include.h                           |   11 
 src/nv_proto.h                             |    7 
 src/nv_shadow.c                            |    3 
 src/nv_type.h                              |   53 
 src/nvc0_accel.c                           |  841 ++--------
 src/nvc0_accel.h                           |  120 -
 src/nvc0_exa.c                             |  974 +++++-------
 src/nvc0_shader.h                          |  444 +++++
 src/nvc0_xv.c                              |  374 +---
 src/nve0_shader.h                          |  460 +++++
 40 files changed, 8045 insertions(+), 5502 deletions(-)

New commits:
commit c20b687c6f92abb63eb019c1778cb5b465ac1b57
Author: Maarten Lankhorst <m.b.lankhorst@gmail.com>
Date:   Wed May 23 10:08:34 2012 +0200

    Add 02-drm-nouveau-newabi.patch to build with old libdrm
    
    Until mesa 8.1 is released, we cannot build with new libdrm yet

diff --git a/debian/changelog b/debian/changelog
index 55d53bb..e96e86b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,8 @@ xserver-xorg-video-nouveau (1:0.0.16+git20120523+5815644-1) UNRELEASED; urgency=
 
   [ Maarten Lankhorst ]
   * New upstream snapshot. First one to have the new ABI.
+  * Add 02-drm-nouveau-newabi.patch to build with old libdrm
+  - Until mesa 8.1 is released, we cannot build with new libdrm yet
 
  -- Maarten Lankhorst <maarten.lankhorst@canonical.com>  Wed, 23 May 2012 09:45:06 +0200
 
diff --git a/debian/patches/02-drm-nouveau-newabi.patch b/debian/patches/02-drm-nouveau-newabi.patch
new file mode 100644
index 0000000..8179f9f
--- /dev/null
+++ b/debian/patches/02-drm-nouveau-newabi.patch
@@ -0,0 +1,2272 @@
+commit d99486bda5601cb887ac898037a2dfad795aeb8f
+Author: Maarten Lankhorst <m.b.lankhorst@gmail.com>
+Date:   Wed May 23 09:29:29 2012 +0200
+
+    awful hack to remove dependency on libdrm_nouveau
+
+diff --git a/configure.ac b/configure.ac
+index afb6cde..7326144 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -67,7 +67,8 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto)
+ XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+ 
+ # Checks for pkg-config packages
+-PKG_CHECK_MODULES(LIBDRM_NOUVEAU, [libdrm_nouveau >= 2.4.25])
++PKG_CHECK_MODULES(LIBDRM_NOUVEAU_DUMMY, [libdrm_nouveau = 0.6])
++PKG_CHECK_MODULES(LIBDRM_NOUVEAU, [libdrm])
+ AC_SUBST(LIBDRM_NOUVEAU_CFLAGS)
+ AC_SUBST(LIBDRM_NOUVEAU_LIBS)
+ 
+diff --git a/drm_nouveau/abi16.c b/drm_nouveau/abi16.c
+new file mode 100644
+index 0000000..69a0a9b
+--- /dev/null
++++ b/drm_nouveau/abi16.c
+@@ -0,0 +1,198 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++
++#include "private.h"
++
++int
++abi16_chan_nv04(struct nouveau_object *obj)
++{
++	struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
++	struct drm_nouveau_channel_alloc req;
++	struct nv04_fifo *nv04 = obj->data;
++	int ret;
++
++	req.fb_ctxdma_handle = nv04->vram;
++	req.tt_ctxdma_handle = nv04->gart;
++
++	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
++				  &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	nv04->base.channel = req.channel;
++	nv04->base.pushbuf = req.pushbuf_domains;
++	nv04->notify = req.notifier_handle;
++	nv04->base.object->handle = req.channel;
++	nv04->base.object->length = sizeof(*nv04);
++	return 0;
++}
++
++int
++abi16_chan_nvc0(struct nouveau_object *obj)
++{
++	struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
++	struct drm_nouveau_channel_alloc req = {};
++	struct nvc0_fifo *nvc0 = obj->data;
++	int ret;
++
++	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
++				  &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	nvc0->base.channel = req.channel;
++	nvc0->base.pushbuf = req.pushbuf_domains;
++	nvc0->notify = req.notifier_handle;
++	nvc0->base.object->handle = req.channel;
++	nvc0->base.object->length = sizeof(*nvc0);
++	return 0;
++}
++
++int
++abi16_engobj(struct nouveau_object *obj)
++{
++	struct drm_nouveau_grobj_alloc req = {
++		obj->parent->handle, obj->handle, obj->oclass
++	};
++	struct nouveau_device *dev;
++	int ret;
++
++	dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
++	ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
++			      &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	obj->length = sizeof(struct nouveau_object *);
++	return 0;
++}
++
++int
++abi16_ntfy(struct nouveau_object *obj)
++{
++	struct nv04_notify *ntfy = obj->data;
++	struct drm_nouveau_notifierobj_alloc req = {
++		obj->parent->handle, ntfy->object->handle, ntfy->length
++	};
++	struct nouveau_device *dev;
++	int ret;
++
++	dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
++	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
++				  &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	ntfy->offset = req.offset;
++	ntfy->object->length = sizeof(*ntfy);
++	return 0;
++}
++
++void
++abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info)
++{
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++
++	nvbo->map_handle = info->map_handle;
++	bo->handle = info->handle;
++	bo->size = info->size;
++	bo->offset = info->offset;
++
++	bo->flags = 0;
++	if (info->domain & NOUVEAU_GEM_DOMAIN_VRAM)
++		bo->flags |= NOUVEAU_BO_VRAM;
++	if (info->domain & NOUVEAU_GEM_DOMAIN_GART)
++		bo->flags |= NOUVEAU_BO_GART;
++	if (!(info->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG))
++		bo->flags |= NOUVEAU_BO_CONTIG;
++	if (nvbo->map_handle)
++		bo->flags |= NOUVEAU_BO_MAP;
++
++	if (bo->device->chipset >= 0xc0) {
++		bo->config.nvc0.memtype   = (info->tile_flags & 0xff00) >> 8;
++		bo->config.nvc0.tile_mode = info->tile_mode;
++	} else
++	if (bo->device->chipset >= 0x80 || bo->device->chipset == 0x50) {
++		bo->config.nv50.memtype   = (info->tile_flags & 0x07f00) >> 8 |
++					    (info->tile_flags & 0x30000) >> 9;
++		bo->config.nv50.tile_mode = info->tile_mode << 4;
++	} else {
++		bo->config.nv04.surf_flags = info->tile_flags & 7;
++		bo->config.nv04.surf_pitch = info->tile_mode;
++	}
++}
++
++int
++abi16_bo_init(struct nouveau_bo *bo, uint32_t alignment,
++	      union nouveau_bo_config *config)
++{
++	struct nouveau_device *dev = bo->device;
++	struct drm_nouveau_gem_new req = {};
++	struct drm_nouveau_gem_info *info = &req.info;
++	int ret;
++
++	if (bo->flags & NOUVEAU_BO_VRAM)
++		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
++	if (bo->flags & NOUVEAU_BO_GART)
++		info->domain |= NOUVEAU_GEM_DOMAIN_GART;
++	if (!info->domain)
++		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM |
++				NOUVEAU_GEM_DOMAIN_GART;
++
++	if (bo->flags & NOUVEAU_BO_MAP)
++		info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
++
++	if (!(bo->flags & NOUVEAU_BO_CONTIG))
++		info->tile_flags = NOUVEAU_GEM_TILE_NONCONTIG;
++
++	info->size = bo->size;
++	req.align = alignment;
++
++	if (config) {
++		if (dev->chipset >= 0xc0) {
++			info->tile_flags = (config->nvc0.memtype & 0xff) << 8;
++			info->tile_mode  = config->nvc0.tile_mode;
++		} else
++		if (dev->chipset >= 0x80 || dev->chipset == 0x50) {
++			info->tile_flags = (config->nv50.memtype & 0x07f) << 8 |
++					   (config->nv50.memtype & 0x180) << 9;
++			info->tile_mode  = config->nv50.tile_mode >> 4;
++		} else {
++			info->tile_flags = config->nv04.surf_flags & 7;
++			info->tile_mode  = config->nv04.surf_pitch;
++		}
++	}
++
++	if (!nouveau_device(dev)->have_bo_usage)
++		info->tile_flags &= 0x0000ff00;
++
++	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW,
++				  &req, sizeof(req));
++	if (ret == 0)
++		abi16_bo_info(bo, &req.info);
++	return ret;
++}
+diff --git a/drm_nouveau/bufctx.c b/drm_nouveau/bufctx.c
+new file mode 100644
+index 0000000..23d6f09
+--- /dev/null
++++ b/drm_nouveau/bufctx.c
+@@ -0,0 +1,170 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include <assert.h>
++#include <errno.h>
++
++#include "libdrm_lists.h"
++
++#include "nouveau.h"
++#include "private.h"
++
++struct nouveau_bufref_priv {
++	struct nouveau_bufref base;
++	struct nouveau_bufref_priv *next;
++	struct nouveau_bufctx *bufctx;
++};
++
++static inline struct nouveau_bufref_priv *
++nouveau_bufref(struct nouveau_bufref *bctx)
++{
++	return (struct nouveau_bufref_priv *)bctx;
++}
++
++struct nouveau_bufbin_priv {
++	struct nouveau_bufref_priv *list;
++	int relocs;
++};
++
++struct nouveau_bufctx_priv {
++	struct nouveau_bufctx base;
++	struct nouveau_bufref_priv *free;
++	int nr_bins;
++	struct nouveau_bufbin_priv bins[];
++};
++
++static inline struct nouveau_bufctx_priv *
++nouveau_bufctx(struct nouveau_bufctx *bctx)
++{
++	return (struct nouveau_bufctx_priv *)bctx;
++}
++
++int
++nouveau_bufctx_new(struct nouveau_client *client, int bins,
++		   struct nouveau_bufctx **pbctx)
++{
++	struct nouveau_bufctx_priv *priv;
++
++	priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
++	if (priv) {
++		DRMINITLISTHEAD(&priv->base.head);
++		DRMINITLISTHEAD(&priv->base.pending);
++		DRMINITLISTHEAD(&priv->base.current);
++		priv->base.client = client;
++		priv->nr_bins = bins;
++		*pbctx = &priv->base;
++		return 0;
++	}
++
++	return -ENOMEM;
++}
++
++void
++nouveau_bufctx_del(struct nouveau_bufctx **pbctx)
++{
++	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
++	struct nouveau_bufref_priv *pref;
++	if (pctx) {
++		while (pctx->nr_bins--)
++			nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
++		while ((pref = pctx->free)) {
++			pctx->free = pref->next;
++			free(pref);
++		}
++		free(pctx);
++		*pbctx = NULL;
++	}
++}
++
++void
++nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
++{
++	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
++	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
++	struct nouveau_bufref_priv *pref;
++
++	while ((pref = pbin->list)) {
++		DRMLISTDELINIT(&pref->base.thead);
++		pbin->list = pref->next;
++		pref->next = pctx->free;
++		pctx->free = pref;
++	}
++
++	bctx->relocs -= pbin->relocs;
++	pbin->relocs  = 0;
++}
++
++struct nouveau_bufref *
++nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
++		    struct nouveau_bo *bo, uint32_t flags)
++{
++	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
++	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
++	struct nouveau_bufref_priv *pref = pctx->free;
++
++	if (!pref)
++		pref = malloc(sizeof(*pref));
++	else
++		pctx->free = pref->next;
++
++	if (pref) {
++		pref->base.bo = bo;
++		pref->base.flags = flags;
++		pref->base.packet = 0;
++
++		DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
++		pref->bufctx = bctx;
++		pref->next = pbin->list;
++		pbin->list = pref;
++	}
++
++	return &pref->base;
++}
++
++struct nouveau_bufref *
++nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
++		    struct nouveau_bo *bo, uint64_t data, uint32_t flags,
++		    uint32_t vor, uint32_t tor)
++{
++	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
++	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
++	struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
++	if (bref) {
++		bref->packet = packet;
++		bref->data = data;
++		bref->vor = vor;
++		bref->tor = tor;
++		pbin->relocs++;
++		bctx->relocs++;
++	}
++	return bref;
++}
+diff --git a/drm_nouveau/libdrm_lists.h b/drm_nouveau/libdrm_lists.h
+new file mode 100644
+index 0000000..8926d8d
+--- /dev/null
++++ b/drm_nouveau/libdrm_lists.h
+@@ -0,0 +1,118 @@
++/**************************************************************************
++ *
++ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
++ * All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
++ * USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ */
++
++/*
++ * List macros heavily inspired by the Linux kernel
++ * list handling. No list looping yet.
++ */
++
++#include <stddef.h>
++
++typedef struct _drmMMListHead
++{
++    struct _drmMMListHead *prev;
++    struct _drmMMListHead *next;
++} drmMMListHead;
++
++#define DRMINITLISTHEAD(__item)		       \
++  do{					       \
++    (__item)->prev = (__item);		       \
++    (__item)->next = (__item);		       \
++  } while (0)
++
++#define DRMLISTADD(__item, __list)		\
++  do {						\
++    (__item)->prev = (__list);			\
++    (__item)->next = (__list)->next;		\
++    (__list)->next->prev = (__item);		\
++    (__list)->next = (__item);			\
++  } while (0)
++
++#define DRMLISTADDTAIL(__item, __list)		\
++  do {						\
++    (__item)->next = (__list);			\
++    (__item)->prev = (__list)->prev;		\
++    (__list)->prev->next = (__item);		\
++    (__list)->prev = (__item);			\
++  } while(0)
++
++#define DRMLISTDEL(__item)			\
++  do {						\
++    (__item)->prev->next = (__item)->next;	\
++    (__item)->next->prev = (__item)->prev;	\
++  } while(0)
++
++#define DRMLISTDELINIT(__item)			\
++  do {						\
++    (__item)->prev->next = (__item)->next;	\
++    (__item)->next->prev = (__item)->prev;	\
++    (__item)->next = (__item);			\
++    (__item)->prev = (__item);			\
++  } while(0)
++
++#define DRMLISTENTRY(__type, __item, __field)   \
++    ((__type *)(((char *) (__item)) - offsetof(__type, __field)))
++
++#define DRMLISTEMPTY(__item) ((__item)->next == (__item))
++
++#define DRMLISTSINGLE(__list) \
++	(!DRMLISTEMPTY(__list) && ((__list)->next == (__list)->prev))
++
++#define DRMLISTFOREACH(__item, __list)					\
++	for ((__item) = (__list)->next;					\
++	     (__item) != (__list); (__item) = (__item)->next)
++
++#define DRMLISTFOREACHSAFE(__item, __temp, __list)			\
++	for ((__item) = (__list)->next, (__temp) = (__item)->next;	\
++	     (__item) != (__list);					\
++	     (__item) = (__temp), (__temp) = (__item)->next)
++
++#define DRMLISTFOREACHSAFEREVERSE(__item, __temp, __list)		\
++	for ((__item) = (__list)->prev, (__temp) = (__item)->prev;	\
++	     (__item) != (__list);					\
++	     (__item) = (__temp), (__temp) = (__item)->prev)
++
++#define DRMLISTFOREACHENTRY(__item, __list, __head)                            \
++	for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head); \
++	     &(__item)->__head != (__list);                                    \
++	     (__item) = DRMLISTENTRY(typeof(*__item),                          \
++				     (__item)->__head.next, __head))
++
++#define DRMLISTFOREACHENTRYSAFE(__item, __temp, __list, __head)                \
++	for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head), \
++	     (__temp) = DRMLISTENTRY(typeof(*__item),                          \
++				     (__item)->__head.next, __head);           \
++	     &(__item)->__head != (__list);                                    \
++	     (__item) = (__temp),                                              \
++	     (__temp) = DRMLISTENTRY(typeof(*__item),                          \
++				     (__temp)->__head.next, __head))
++
++#define DRMLISTJOIN(__list, __join) if (!DRMLISTEMPTY(__list)) {	\
++	(__list)->next->prev = (__join);				\
++	(__list)->prev->next = (__join)->next;				\
++	(__join)->next->prev = (__list)->prev;				\
++	(__join)->next = (__list)->next;				\
++}
+diff --git a/drm_nouveau/nouveau.c b/drm_nouveau/nouveau.c
+new file mode 100644
+index 0000000..5aa4107
+--- /dev/null
++++ b/drm_nouveau/nouveau.c
+@@ -0,0 +1,492 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <stdbool.h>
++#include <assert.h>
++#include <errno.h>
++#include <sys/mman.h>
++
++#include <xf86drm.h>
++#include <xf86atomic.h>
++#include "libdrm_lists.h"
++#include "nouveau_drm.h"
++
++#include "nouveau.h"
++#include "private.h"
++
++#ifdef DEBUG
++uint32_t nouveau_debug = 0;
++
++static void
++debug_init(char *args)
++{
++	if (args) {
++		int n = strtol(args, NULL, 0);
++		if (n >= 0)
++			nouveau_debug = n;
++	}
++}
++#endif
++
++/* this is the old libdrm's version of nouveau_device_wrap(), the symbol
++ * is kept here to prevent AIGLX from crashing if the DDX is linked against
++ * the new libdrm, but the DRI driver against the old
++ */
++int
++nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd,
++			     drm_context_t ctx)
++{
++	return -EACCES;
++}
++
++int
++nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev)
++{
++	struct nouveau_device_priv *nvdev = calloc(1, sizeof(*nvdev));
++	struct nouveau_device *dev = &nvdev->base;
++	uint64_t chipset, vram, gart, bousage;
++	drmVersionPtr ver;
++	int ret;
++
++#ifdef DEBUG
++	debug_init(getenv("NOUVEAU_LIBDRM_DEBUG"));
++#endif
++
++	if (!nvdev)
++		return -ENOMEM;
++	nvdev->base.fd = fd;
++
++	ver = drmGetVersion(fd);
++	if (ver) dev->drm_version = (ver->version_major << 24) |
++				    (ver->version_minor << 8) |
++				     ver->version_patchlevel;
++	drmFreeVersion(ver);
++
++	if ( dev->drm_version != 0x00000010 &&
++	    (dev->drm_version <  0x01000000 ||
++	     dev->drm_version >= 0x02000000)) {
++		nouveau_device_del(&dev);
++		return -EINVAL;
++	}
++
++	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset);
++	if (ret == 0)
++	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram);
++	if (ret == 0)
++	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart);
++	if (ret) {
++		nouveau_device_del(&dev);
++		return ret;
++	}
++
++	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage);
++	if (ret == 0)
++		nvdev->have_bo_usage = (bousage != 0);
++
++	nvdev->close = close;
++	DRMINITLISTHEAD(&nvdev->bo_list);
++	nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
++	nvdev->base.lib_version = 0x01000000;
++	nvdev->base.chipset = chipset;
++	nvdev->base.vram_size = vram;
++	nvdev->base.gart_size = gart;
++	nvdev->base.vram_limit = (nvdev->base.vram_size * 80) / 100;
++	nvdev->base.gart_limit = (nvdev->base.gart_size * 80) / 100;
++
++	*pdev = &nvdev->base;
++	return 0;
++}
++
++int
++nouveau_device_open(const char *busid, struct nouveau_device **pdev)
++{
++	int ret = -ENODEV, fd = drmOpen("nouveau", busid);
++	if (fd >= 0) {
++		ret = nouveau_device_wrap(fd, 1, pdev);
++		if (ret)
++			drmClose(fd);
++	}
++	return ret;
++}
++
++void
++nouveau_device_del(struct nouveau_device **pdev)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
++	if (nvdev) {
++		if (nvdev->close)
++			drmClose(nvdev->base.fd);
++		free(nvdev->client);
++		free(nvdev);
++		*pdev = NULL;
++	}
++}
++
++int
++nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value)
++{
++	struct drm_nouveau_getparam r = { param, 0 };
++	int fd = dev->fd, ret =
++		drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r));
++	*value = r.value;
++	return ret;
++}
++
++int
++nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value)
++{
++	struct drm_nouveau_setparam r = { param, value };
++	return drmCommandWrite(dev->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r));
++}
++
++int
++nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct nouveau_client_priv *pcli;
++	int id = 0, i, ret = -ENOMEM;
++	uint32_t *clients;
++
++	for (i = 0; i < nvdev->nr_client; i++) {
++		id = ffs(nvdev->client[i]) - 1;
++		if (id >= 0)
++			goto out;
++	}
++
++	clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1));
++	if (!clients)
++		return ret;
++	nvdev->client = clients;
++	nvdev->client[i] = 0;
++	nvdev->nr_client++;
++
++out:
++	pcli = calloc(1, sizeof(*pcli));
++	if (pcli) {
++		nvdev->client[i] |= (1 << id);
++		pcli->base.device = dev;
++		pcli->base.id = (i * 32) + id;
++		ret = 0;
++	}
++
++	*pclient = &pcli->base;
++	return ret;
++}
++
++void
++nouveau_client_del(struct nouveau_client **pclient)
++{
++	struct nouveau_client_priv *pcli = nouveau_client(*pclient);
++	struct nouveau_device_priv *nvdev;
++	if (pcli) {
++		int id = pcli->base.id;
++		nvdev = nouveau_device(pcli->base.device);
++		nvdev->client[id / 32] &= ~(1 << (id % 32));
++		free(pcli->kref);
++		free(pcli);
++	}
++}
++
++int
++nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
++		   uint32_t oclass, void *data, uint32_t length,
++		   struct nouveau_object **pobj)
++{
++	struct nouveau_device *dev;
++	struct nouveau_object *obj;
++	int ret = -EINVAL;
++
++	if (length == 0)
++		length = sizeof(struct nouveau_object *);
++	obj = malloc(sizeof(*obj) + length);
++	obj->parent = parent;
++	obj->handle = handle;
++	obj->oclass = oclass;
++	obj->length = length;
++	obj->data = obj + 1;
++	if (data)
++		memcpy(obj->data, data, length);
++	*(struct nouveau_object **)obj->data = obj;
++
++	dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
++	switch (parent->oclass) {
++	case NOUVEAU_DEVICE_CLASS:
++		switch (obj->oclass) {
++		case NOUVEAU_FIFO_CHANNEL_CLASS:
++		{
++			if (dev->chipset < 0xc0)
++				ret = abi16_chan_nv04(obj);
++			else
++				ret = abi16_chan_nvc0(obj);
++		}
++			break;
++		default:
++			break;
++		}
++		break;
++	case NOUVEAU_FIFO_CHANNEL_CLASS:
++		switch (obj->oclass) {
++		case NOUVEAU_NOTIFIER_CLASS:
++			ret = abi16_ntfy(obj);
++			break;
++		default:
++			ret = abi16_engobj(obj);
++			break;
++		}
++	default:
++		break;
++	}
++
++	if (ret) {
++		free(obj);
++		return ret;
++	}
++
++	*pobj = obj;
++	return 0;
++}
++
++void
++nouveau_object_del(struct nouveau_object **pobj)
++{
++	struct nouveau_object *obj = *pobj;
++	struct nouveau_device *dev;
++	if (obj) {
++		dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
++		if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) {
++			struct drm_nouveau_channel_free req;
++			req.channel = obj->handle;
++			drmCommandWrite(dev->fd, DRM_NOUVEAU_CHANNEL_FREE,
++					&req, sizeof(req));
++		} else {
++			struct drm_nouveau_gpuobj_free req;
++			req.channel = obj->parent->handle;
++			req.handle  = obj->handle;
++			drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
++					&req, sizeof(req));
++		}
++	}
++	free(obj);
++	*pobj = NULL;
++}
++
++void *
++nouveau_object_find(struct nouveau_object *obj, uint32_t pclass)
++{
++	while (obj && obj->oclass != pclass) {
++		obj = obj->parent;
++		if (pclass == NOUVEAU_PARENT_CLASS)
++			break;
++	}
++	return obj;
++}
++
++static void
++nouveau_bo_del(struct nouveau_bo *bo)
++{
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	struct drm_gem_close req = { bo->handle };
++	DRMLISTDEL(&nvbo->head);
++	if (bo->map)
++		munmap(bo->map, bo->size);
++	drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
++	free(nvbo);
++}
++
++int
++nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align,
++	       uint64_t size, union nouveau_bo_config *config,
++	       struct nouveau_bo **pbo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
++	struct nouveau_bo *bo = &nvbo->base;
++	int ret;
++
++	if (!nvbo)
++		return -ENOMEM;
++	atomic_set(&nvbo->refcnt, 1);
++	bo->device = dev;
++	bo->flags = flags;
++	bo->size = size;
++
++	ret = abi16_bo_init(bo, align, config);
++	if (ret) {
++		free(nvbo);
++		return ret;
++	}
++
++	DRMLISTADD(&nvbo->head, &nvdev->bo_list);
++
++	*pbo = bo;
++	return 0;
++}
++
++int
++nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
++		struct nouveau_bo **pbo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct drm_nouveau_gem_info req = { .handle = handle };
++	struct nouveau_bo_priv *nvbo;
++	int ret;
++
++	DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
++		if (nvbo->base.handle == handle) {
++			*pbo = NULL;
++			nouveau_bo_ref(&nvbo->base, pbo);
++			return 0;
++		}
++	}
++
++	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO,
++				  &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	nvbo = calloc(1, sizeof(*nvbo));
++	if (nvbo) {
++		atomic_set(&nvbo->refcnt, 1);
++		nvbo->base.device = dev;
++		abi16_bo_info(&nvbo->base, &req);
++		DRMLISTADD(&nvbo->head, &nvdev->bo_list);
++		*pbo = &nvbo->base;
++		return 0;
++	}
++
++	return -ENOMEM;
++}
++
++int
++nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
++		    struct nouveau_bo **pbo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct nouveau_bo_priv *nvbo;
++	struct drm_gem_open req = { .name = name };
++	int ret;
++
++	DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
++		if (nvbo->name == name) {
++			*pbo = NULL;


Reply to: