configure.ac          |    2 
 man/nouveau.man       |   18 +++
 src/drmmode_display.c |  265 +++++++++++++++++++++++++++++++++-----------
 src/nouveau_class.h   |    2 
 src/nouveau_dri2.c    |  298 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/nouveau_exa.c     |   52 +-------
 src/nouveau_local.h   |   11 +
 src/nouveau_wfb.c     |    2 
 src/nouveau_xv.c      |   17 --
 src/nv04_exa.c        |   35 +++++
 src/nv04_xv_blit.c    |   11 -
 src/nv30_xv_tex.c     |   19 ---
 src/nv40_xv_tex.c     |   19 ---
 src/nv50_accel.c      |   33 +++++
 src/nv50_xv.c         |   32 -----
 src/nv_accel_common.c |   95 +++++++++++++++
 src/nv_const.h        |    8 +
 src/nv_dma.c          |    3 
 src/nv_driver.c       |  107 +++++++++++------
 src/nv_include.h      |    2 
 src/nv_proto.h        |   14 +-
 src/nv_type.h         |    8 +
 22 files changed, 806 insertions(+), 247 deletions(-)

New commits:
commit 8bb8231236a6b877895663aeaa9cef731d67fe68
Author: Ben Skeggs <bske...@redhat.com>
Date:   Tue Nov 30 15:27:36 2010 +1000

    dri2: fix certain clients blocking forever when sync-to-vblank unavailable
    
    Signed-off-by: Ben Skeggs <bske...@redhat.com>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 969c6f3..2dd6da4 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -322,8 +322,10 @@ nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr 
draw,
        CARD64 current_msc;
        int ret;
 
-       if (!can_sync_to_vblank(draw))
+       if (!can_sync_to_vblank(draw)) {
+               DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
                return TRUE;
+       }
 
        /* Initialize a vblank structure */
        s = malloc(sizeof(*s));

commit f29afe65b67c9b89ceba421d9b3aee590f7ded20
Author: Ben Skeggs <bske...@redhat.com>
Date:   Mon Nov 29 09:23:35 2010 +1000

    dri2: don't return failure from get_msc if sync-to-vblank isn't available
    
    Signed-off-by: Ben Skeggs <bske...@redhat.com>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 48e134e..969c6f3 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -363,8 +363,11 @@ nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 
*msc)
 {
        int ret;
 
-       if (!can_sync_to_vblank(draw))
-               return FALSE;
+       if (!can_sync_to_vblank(draw)) {
+               *ust = 0;
+               *msc = 0;
+               return TRUE;
+       }
 
        /* Get current sequence */
        ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL);

commit 4b1d26578116f4d1745dd92a7c99413972a2bedf
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Thu Nov 25 21:33:46 2010 +0100

    dri2: Don't return failure from schedule_wait if sync-to-vblank is 
unavailable.
    
    Reported-by: Ben Skeggs <bske...@redhat.com>
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 204ab32..48e134e 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -323,7 +323,7 @@ nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr 
draw,
        int ret;
 
        if (!can_sync_to_vblank(draw))
-               return FALSE;
+               return TRUE;
 
        /* Initialize a vblank structure */
        s = malloc(sizeof(*s));

commit 1143e7a97dce1b741376e178b73b8b766e03849a
Author: Jesse Adkins <jesserayadk...@gmail.com>
Date:   Tue Oct 26 16:05:32 2010 -0700

    Purge cvs tags.
    
    Signed-off-by: Jesse Adkins <jesserayadk...@gmail.com>
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nv_const.h b/src/nv_const.h
index f80d125..01ffc2c 100644
--- a/src/nv_const.h
+++ b/src/nv_const.h
@@ -1,5 +1,3 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_const.h,v 1.6 
2001/12/07 00:09:55 mvojkovi Exp $ */
-
 #ifndef __NV_CONST_H__
 #define __NV_CONST_H__
 
diff --git a/src/nv_include.h b/src/nv_include.h
index ce89596..48f0b21 100644
--- a/src/nv_include.h
+++ b/src/nv_include.h
@@ -1,5 +1,3 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_include.h,v 1.9 
2000/10/06 12:31:03 eich Exp $ */
-
 #ifndef __NV_INCLUDE_H__
 #define __NV_INCLUDE_H__
 

commit 22020457f43eceaf26532ecb50e46d743f4a691f
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Tue Oct 26 00:24:06 2010 +0200

    dri2: Fix throttling on occluded drawables.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 65e7340..204ab32 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -239,6 +239,13 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
                DamageRegionProcessPending(draw);
        } else {
                type = DRI2_BLIT_COMPLETE;
+
+               /* Reference the front buffer to let throttling work
+                * on occluded drawables. */
+               WAIT_RING(chan, 1);
+               OUT_RELOC(chan, dst_bo, 0,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, 0, 0);
+
                REGION_TRANSLATE(0, &reg, -draw->x, -draw->y);
                nouveau_dri2_copy_region(draw, &reg, s->dst, s->src);
        }

commit 9737a812aacbc544b93eeaa031cf1c2e8adbd661
Author: Ben Skeggs <bske...@redhat.com>
Date:   Mon Oct 25 10:37:08 2010 +1000

    kms: initial pass at supporting zaphod-mode
    
    This works ok from some simple testing, there's undoubtedly things that
    will need polishing still however.
    
    Signed-off-by: Ben Skeggs <bske...@redhat.com>

diff --git a/man/nouveau.man b/man/nouveau.man
index a8961ad..39de690 100644
--- a/man/nouveau.man
+++ b/man/nouveau.man
@@ -80,6 +80,16 @@ Enable or disable wfb, only affects nv50+. Useful for some 
legacy configurations
 Synchronize GLX clients to VBlank. Useful where tearing is a problem,
 harmful if the GPU isn't fast enough to keep up with the monitor
 refresh rate. Default: off.
+.TP
+.BI "Option \*qZaphodHeads\*q \*q" string \*q
+Specify the randr output(s) to use with zaphod mode for a particular driver
+instance.  If you use this option you most use this option for all instances
+of the driver.
+.br
+For example:
+.B
+Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q
+will assign xrandr outputs LVDS and VGA-0 to this instance of the driver.
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), 
Xserver(__appmansuffix__), X(__miscmansuffix__)
 .SH AUTHORS
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 94b19ea..c5b57eb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -945,13 +945,48 @@ const char *output_names[] = { "None",
 };
 #define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
 
+static Bool
+drmmode_zaphod_match(ScrnInfoPtr pScrn, const char *s, char *output_name)
+{
+    int i = 0;
+    char s1[20];
+
+    do {
+       switch(*s) {
+       case ',':
+           s1[i] = '\0';
+           i = 0;
+           if (strcmp(s1, output_name) == 0)
+               return TRUE;
+           break;
+       case ' ':
+       case '\t':
+       case '\n':
+       case '\r':
+           break;
+       default:
+           s1[i] = *s;
+           i++;
+           break;
+       }
+    } while(*s++);
+
+    s1[i] = '\0';
+    if (strcmp(s1, output_name) == 0)
+       return TRUE;
+
+    return FALSE;
+}
+
 static void
 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 {
+       NVPtr pNv = NVPTR(pScrn);
        xf86OutputPtr output;
        drmModeConnectorPtr koutput;
        drmModeEncoderPtr kencoder;
        drmmode_output_private_ptr drmmode_output;
+       const char *s;
        char name[32];
 
        koutput = drmModeGetConnector(drmmode->fd,
@@ -973,6 +1008,28 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr 
drmmode, int num)
                         output_names[koutput->connector_type],
                         koutput->connector_type_id);
 
+       if (xf86IsEntityShared(pScrn->entityList[0])) {
+               s = xf86GetOptValString(pNv->Options, OPTION_ZAPHOD_HEADS);
+               if (s) {
+                       if (!drmmode_zaphod_match(pScrn, s, name)) {
+                               drmModeFreeEncoder(kencoder);
+                               drmModeFreeConnector(koutput);
+                               return;
+                       }
+               } else {
+                       if (pNv->Primary && (num != 0)) {
+                               drmModeFreeEncoder(kencoder);
+                               drmModeFreeConnector(koutput);
+                               return;
+                       } else
+                       if (pNv->Secondary && (num != 1)) {
+                               drmModeFreeEncoder(kencoder);
+                               drmModeFreeConnector(koutput);
+                               return;
+                       }
+               }
+       }
+
        output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
        if (!output) {
                drmModeFreeEncoder(kencoder);
@@ -1003,8 +1060,6 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr 
drmmode, int num)
 
        output->interlaceAllowed = true;
        output->doubleScanAllowed = true;
-
-       return;
 }
 
 static Bool
@@ -1121,8 +1176,11 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
 
        xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
                             drmmode->mode_res->max_height);
-       for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
-               drmmode_crtc_init(pScrn, drmmode, i);
+       for (i = 0; i < drmmode->mode_res->count_crtcs; i++) {
+               if (!xf86IsEntityShared(pScrn->entityList[0] ||
+                    pScrn->confScreen->device->screen == i))
+                       drmmode_crtc_init(pScrn, drmmode, i);
+       }
 
        for (i = 0; i < drmmode->mode_res->count_connectors; i++)
                drmmode_output_init(pScrn, drmmode, i);
diff --git a/src/nv_const.h b/src/nv_const.h
index c355cad..f80d125 100644
--- a/src/nv_const.h
+++ b/src/nv_const.h
@@ -15,6 +15,7 @@ typedef enum {
     OPTION_VIDEO_KEY,
     OPTION_WFB,
     OPTION_GLX_VBLANK,
+    OPTION_ZAPHOD_HEADS,
 } NVOpts;
 
 
@@ -26,6 +27,7 @@ static const OptionInfoRec NVOptions[] = {
     { OPTION_VIDEO_KEY,                "VideoKey",     OPTV_INTEGER,   {0}, 
FALSE },
     { OPTION_WFB,              "WrappedFB",    OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_GLX_VBLANK,       "GLXVBlank",    OPTV_BOOLEAN,   {0}, FALSE },
+    { OPTION_ZAPHOD_HEADS,     "ZaphodHeads",  OPTV_STRING,    {0}, FALSE },
     { -1,                       NULL,           OPTV_NONE,      {0}, FALSE }
 };
 
diff --git a/src/nv_driver.c b/src/nv_driver.c
index fad7d6a..f351fac 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -205,6 +205,7 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device 
*pci_dev,
                { -1, -1, NULL }
        };
        struct nouveau_device *dev = NULL;
+       EntityInfoPtr pEnt = NULL;
        ScrnInfoPtr pScrn = NULL;
        drmVersion *version;
        int chipset, ret;
@@ -280,6 +281,12 @@ NVPciProbe(DriverPtr drv, int entity_num, struct 
pci_device *pci_dev,
        pScrn->LeaveVT          = NVLeaveVT;
        pScrn->FreeScreen       = NVFreeScreen;
 
+       xf86SetEntitySharable(entity_num);
+
+       pEnt = xf86GetEntityInfo(entity_num);
+       xf86SetEntityInstanceForScreen(pScrn, pEnt->index, 
xf86GetNumEntityInstances(pEnt->index) - 1);
+       free(pEnt);
+
        return TRUE;
 }
 
@@ -628,10 +635,18 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
        pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
        if (pNv->pEnt->location.type != BUS_PCI)
                return FALSE;
- 
+
+       if (xf86IsEntityShared(pScrn->entityList[0])) {
+               if(!xf86IsPrimInitDone(pScrn->entityList[0])) {
+                       pNv->Primary = TRUE;
+                       xf86SetPrimInitDone(pScrn->entityList[0]);
+               } else {
+                       pNv->Secondary = TRUE;
+               }
+        }
+
        /* Find the PCI info for this screen */
        pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index);
-       pNv->Primary = xf86IsPrimaryPci(pNv->PciInfo);
 
        /* Initialise the kernel module */
        if (!NVPreInitDRM(pScrn))
diff --git a/src/nv_type.h b/src/nv_type.h
index 94c385a..4204556 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -33,6 +33,7 @@ typedef struct _NVRec {
     EntityInfoPtr       pEnt;
        struct pci_device *PciInfo;
     Bool                Primary;
+    Bool               Secondary;
 
     /* Various pinned memory regions */
     struct nouveau_bo * scanout;

commit d40c16f5497739c0215f37566db1651a74cb20ba
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Sat Oct 23 02:20:30 2010 +0200

    dri2: Fix build on X server 1.8.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 35146f2..65e7340 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -201,8 +201,8 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
        RegionRec reg;
        int type, ret;
 
-       RegionInit(&reg, &(BoxRec){ 0, 0, draw->width, draw->height }, 0);
-       RegionTranslate(&reg, draw->x, draw->y);
+       REGION_INIT(0, &reg, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0);
+       REGION_TRANSLATE(0, &reg, draw->x, draw->y);
 
        /* Throttle on the previous frame before swapping */
        nouveau_bo_map(dst_bo, NOUVEAU_BO_RD);
@@ -215,16 +215,16 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
                          NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, 0, 0);
 
                if (pNv->Architecture >= NV_ARCH_50)
-                       NV50SyncToVBlank(dst_pix, RegionExtents(&reg));
+                       NV50SyncToVBlank(dst_pix, REGION_EXTENTS(0, &reg));
                else
-                       NV11SyncToVBlank(dst_pix, RegionExtents(&reg));
+                       NV11SyncToVBlank(dst_pix, REGION_EXTENTS(0, &reg));
 
                FIRE_RING(chan);
        }
 
        if (can_exchange(draw, dst_pix, src_pix)) {
                type = DRI2_EXCHANGE_COMPLETE;
-               DamageRegionAppend (draw, &reg);
+               DamageRegionAppend(draw, &reg);
 
                if (DRI2CanFlip(draw)) {
                        type = DRI2_FLIP_COMPLETE;
@@ -239,7 +239,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
                DamageRegionProcessPending(draw);
        } else {
                type = DRI2_BLIT_COMPLETE;
-               RegionTranslate(&reg, -draw->x, -draw->y);
+               REGION_TRANSLATE(0, &reg, -draw->x, -draw->y);
                nouveau_dri2_copy_region(draw, &reg, s->dst, s->src);
        }
 

commit a4d580bf05d7aac1d486e5d1ba9a2201c026e5f5
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Fri Oct 22 23:09:30 2010 +0200

    Bump the required X server version to 1.8.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/configure.ac b/configure.ac
index 1c39923..676c2a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,7 +71,7 @@ PKG_CHECK_MODULES(LIBDRM_NOUVEAU, libdrm_nouveau)
 AC_SUBST(LIBDRM_NOUVEAU_CFLAGS)
 AC_SUBST(LIBDRM_NOUVEAU_LIBS)
 
-PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7] xproto fontsproto libdrm 
xf86driproto $REQUIRED_MODULES)
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.8] xproto fontsproto libdrm 
xf86driproto $REQUIRED_MODULES)
 PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1],
                  HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, 
[xextproto 7.1 available]),
                  HAVE_XEXTPROTO_71="no")

commit d0f2e16bc35660d01d3cd20a770cf8e613ab5323
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Fri Oct 22 23:06:28 2010 +0200

    dri2: Report damage on page-flipped drawables.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index b006cfc..35146f2 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -224,6 +224,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
 
        if (can_exchange(draw, dst_pix, src_pix)) {
                type = DRI2_EXCHANGE_COMPLETE;
+               DamageRegionAppend (draw, &reg);
 
                if (DRI2CanFlip(draw)) {
                        type = DRI2_FLIP_COMPLETE;
@@ -235,6 +236,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
                SWAP(s->dst->name, s->src->name);
                SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo);
 
+               DamageRegionProcessPending(draw);
        } else {
                type = DRI2_BLIT_COMPLETE;
                RegionTranslate(&reg, -draw->x, -draw->y);

commit c61e8d03161adcfbba4162172153814accf9e86b
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Fri Oct 22 23:05:24 2010 +0200

    Make the sync-to-vblank helpers take a box as argument.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index c8d5c57..b006cfc 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -198,26 +198,26 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
        struct nouveau_bo *dst_bo = nouveau_pixmap_bo(dst_pix);
        struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix);
        struct nouveau_channel *chan = pNv->chan;
+       RegionRec reg;
        int type, ret;
 
+       RegionInit(&reg, &(BoxRec){ 0, 0, draw->width, draw->height }, 0);
+       RegionTranslate(&reg, draw->x, draw->y);
+
        /* Throttle on the previous frame before swapping */
        nouveau_bo_map(dst_bo, NOUVEAU_BO_RD);
        nouveau_bo_unmap(dst_bo);
 
        if (can_sync_to_vblank(draw)) {
-               int x1 = draw->x, y1 = draw->y,
-                       x2 = draw->x + draw->width,
-                       y2 = draw->y + draw->height;
-
                /* Reference the back buffer to sync it to vblank */
                WAIT_RING(chan, 1);
                OUT_RELOC(chan, src_bo, 0,
                          NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, 0, 0);
 
                if (pNv->Architecture >= NV_ARCH_50)
-                       NV50SyncToVBlank(dst_pix, x1, y1, x2, y2);
+                       NV50SyncToVBlank(dst_pix, RegionExtents(&reg));
                else
-                       NV11SyncToVBlank(dst_pix, x1, y1, x2, y2);
+                       NV11SyncToVBlank(dst_pix, RegionExtents(&reg));
 
                FIRE_RING(chan);
        }
@@ -236,13 +236,9 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
                SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo);
 
        } else {
-               BoxRec box = { 0, 0, draw->width, draw->height };
-               RegionRec region;
-
-               RegionInit(&region, &box, 0);
-
                type = DRI2_BLIT_COMPLETE;
-               nouveau_dri2_copy_region(draw, &region, s->dst, s->src);
+               RegionTranslate(&reg, -draw->x, -draw->y);
+               nouveau_dri2_copy_region(draw, &reg, s->dst, s->src);
        }
 
        /*
diff --git a/src/nv04_xv_blit.c b/src/nv04_xv_blit.c
index 55d82c4..be39c0d 100644
--- a/src/nv04_xv_blit.c
+++ b/src/nv04_xv_blit.c
@@ -130,8 +130,7 @@ NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, 
int src_offset,
 
         if(pPriv->SyncToVBlank) {
                 FIRE_RING(chan);
-               NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1,
-                                dstBox->x2, dstBox->y2);
+               NV11SyncToVBlank(ppix, dstBox);
         }
 
         if (pNv->dev->chipset >= 0x05) {
diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c
index 61558e9..ffa68e4 100644
--- a/src/nv30_xv_tex.c
+++ b/src/nv30_xv_tex.c
@@ -350,8 +350,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo 
*src, int src_offset,
        /* Just before rendering we wait for vblank in the non-composited case. 
*/
        if (pPriv->SyncToVBlank) {
                FIRE_RING(chan);
-               NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1,
-                                dstBox->x2, dstBox->y2);
+               NV11SyncToVBlank(ppix, dstBox);
        }
 
        /* These are fixed point values in the 16.16 format. */
diff --git a/src/nv40_xv_tex.c b/src/nv40_xv_tex.c
index 602bb7a..e0444e8 100644
--- a/src/nv40_xv_tex.c
+++ b/src/nv40_xv_tex.c
@@ -339,8 +339,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn,
        /* Just before rendering we wait for vblank in the non-composited case. 
*/
        if (pPriv->SyncToVBlank) {
                FIRE_RING(chan);
-               NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1,
-                                dstBox->x2, dstBox->y2);
+               NV11SyncToVBlank(ppix, dstBox);
        }
 
        /* These are fixed point values in the 16.16 format. */
diff --git a/src/nv50_accel.c b/src/nv50_accel.c
index d0def57..95d1886 100644
--- a/src/nv50_accel.c
+++ b/src/nv50_accel.c
@@ -24,7 +24,7 @@
 #include "nv50_accel.h"
 
 void
-NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2)
+NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box)
 {
        ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
        NVPtr pNv = NVPTR(pScrn);
@@ -35,7 +35,9 @@ NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int 
y2)
        if (!nouveau_exa_pixmap_is_onscreen(ppix))
                return;
 
-       crtcs = nv_window_belongs_to_crtc(pScrn, x1, y1, x2 - x1, y2 - y1);
+       crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1,
+                                         box->x2 - box->x1,
+                                         box->y2 - box->y1);
        if (!crtcs)
                return;
 
diff --git a/src/nv50_xv.c b/src/nv50_xv.c
index 87e22b5..e02f86d 100644
--- a/src/nv50_xv.c
+++ b/src/nv50_xv.c
@@ -289,8 +289,7 @@ nv50_xv_image_put(ScrnInfoPtr pScrn,
                return BadAlloc;
 
        if (pPriv->SyncToVBlank) {
-               NV50SyncToVBlank(ppix, dstBox->x1, dstBox->y1,
-                                dstBox->x2, dstBox->y2);
+               NV50SyncToVBlank(ppix, dstBox);
        }
 
        /* These are fixed point values in the 16.16 format. */
diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c
index 3739c79..1ade291 100644
--- a/src/nv_accel_common.c
+++ b/src/nv_accel_common.c
@@ -90,7 +90,7 @@ nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int 
height, int bpp,
 }
 
 void
-NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2)
+NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box)
 {
        ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
        NVPtr pNv = NVPTR(pScrn);
@@ -101,7 +101,9 @@ NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, 
int y2)
        if (!nouveau_exa_pixmap_is_onscreen(ppix))
                return;
 
-       crtcs = nv_window_belongs_to_crtc(pScrn, x1, y1, x2 - x1, y2 - y1);
+       crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1,
+                                         box->x2 - box->x1,
+                                         box->y2 - box->y1);
        if (!crtcs)
                return;
 
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 8514af9..888e74e 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -17,7 +17,7 @@ Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int 
*fmt_ret);
 Bool NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPix, int *fmt_ret);
 PixmapPtr NVGetDrawablePixmap(DrawablePtr pDraw);
 void NVAccelFree(ScrnInfoPtr pScrn);
-void NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2);
+void NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box);
 Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height,
                              int bpp, int usage_hint, int *pitch,
                              struct nouveau_bo **bo);
@@ -132,7 +132,7 @@ int NV40GetTexturePortAttribute(ScrnInfoPtr, Atom, INT32 *, 
pointer);
 int NV40SetTexturePortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 
 /* in nv50_accel.c */
-void NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2);
+void NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box);
 Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn);
 
 /* in nv50_exa.c */

commit a685a5c3be12f3e95a6ec1140af115e7ef28fcaa
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Wed Oct 13 18:45:04 2010 +0200

    dri2: Implement the ScheduleWaitMSC/GetMSC hooks.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 7fdfa9c..c8d5c57 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -116,7 +116,8 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr 
pRegion,
 
 struct nouveau_dri2_vblank_state {
        enum {
-               SWAP
+               SWAP,
+               WAIT
        } action;
 
        ClientPtr client;
@@ -308,6 +309,66 @@ fail:
        return FALSE;
 }
 
+static Bool
+nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw,
+                          CARD64 target_msc, CARD64 divisor, CARD64 remainder)
+{
+       struct nouveau_dri2_vblank_state *s;
+       CARD64 current_msc;
+       int ret;
+
+       if (!can_sync_to_vblank(draw))
+               return FALSE;
+
+       /* Initialize a vblank structure */
+       s = malloc(sizeof(*s));
+       if (!s)
+               return FALSE;
+
+       *s = (struct nouveau_dri2_vblank_state) { WAIT, client, draw->id };
+
+       /* Get current sequence */
+       ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0,
+                                 &current_msc, NULL, NULL);
+       if (ret)
+               goto fail;
+
+       /* Calculate a wait target if we don't have one */
+       if (current_msc > target_msc && divisor)
+               target_msc = current_msc + divisor
+                       - (current_msc - remainder) % divisor;
+
+       /* Request a vblank event */
+       ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE |
+                                 DRM_VBLANK_EVENT,
+                                 max(current_msc, target_msc),
+                                 NULL, NULL, s);
+       if (ret)
+               goto fail;
+
+       DRI2BlockClient(client, draw);
+       return TRUE;
+fail:
+       free(s);
+       return FALSE;
+}
+
+static Bool
+nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
+{
+       int ret;
+
+       if (!can_sync_to_vblank(draw))
+               return FALSE;
+
+       /* Get current sequence */
+       ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL);
+       if (ret)
+               return FALSE;
+
+       return TRUE;
+}
+
 void
 nouveau_dri2_vblank_handler(int fd, unsigned int frame,
                            unsigned int tv_sec, unsigned int tv_usec,
@@ -326,6 +387,11 @@ nouveau_dri2_vblank_handler(int fd, unsigned int frame,
        case SWAP:
                nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s);
                break;
+
+       case WAIT:
+               DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec);
+               free(s);
+               break;
        }
 }
 
@@ -349,6 +415,8 @@ nouveau_dri2_init(ScreenPtr pScreen)
        dri2.DestroyBuffer = nouveau_dri2_destroy_buffer;
        dri2.CopyRegion = nouveau_dri2_copy_region;
        dri2.ScheduleSwap = nouveau_dri2_schedule_swap;
+       dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait;
+       dri2.GetMSC = nouveau_dri2_get_msc;
 
        return DRI2ScreenInit(pScreen, &dri2);
 }

commit eb83c830c87bce345748edef3b50660246143db7
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Thu Oct 21 22:57:08 2010 +0200

    dri2: Add pageflip/exchange support.
    
    Signed-off-by: Francisco Jerez <curroje...@riseup.net>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 4220cf5..94b19ea 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1179,9 +1179,47 @@ drmmode_cursor_init(ScreenPtr pScreen)
        return xf86_cursors_init(pScreen, size, size, flags);
 }
 
-#ifdef HAVE_LIBUDEV
+Bool
+drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv)
+{
+       ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum];
+       xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+       drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private;
+       drmmode_ptr mode = crtc->drmmode;
+       int ret, i, old_fb_id;
+
+       old_fb_id = mode->fb_id;
+       ret = drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
+                          scrn->depth, scrn->bitsPerPixel,
+                          scrn->displayWidth * scrn->bitsPerPixel / 8,
+                          nouveau_pixmap_bo(back)->handle, &mode->fb_id);
+       if (ret) {
+               xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                          "add fb failed: %s\n", strerror(errno));
+               return FALSE;
+       }
+
+       for (i = 0; i < config->num_crtc; i++) {
+               crtc = config->crtc[i]->driver_private;
 
+               if (!config->crtc[i]->enabled)
+                       continue;
 
+               ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id,
+                                     mode->fb_id, 0, priv);
+               if (ret) {
+                       xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                                  "flip queue failed: %s\n", strerror(errno));
+                       return FALSE;
+               }
+       }
+
+       drmModeRmFB(mode->fd, old_fb_id);
+
+       return TRUE;
+}
+
+#ifdef HAVE_LIBUDEV
 static void
 drmmode_handle_uevents(ScrnInfoPtr scrn)
 {
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 66fe16c..7fdfa9c 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -129,6 +129,20 @@ struct nouveau_dri2_vblank_state {
 };
 
 static Bool
+can_exchange(DrawablePtr draw, PixmapPtr dst_pix, PixmapPtr src_pix)
+{
+       ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum];
+       NVPtr pNv = NVPTR(scrn);
+
+       return (!nouveau_exa_pixmap_is_onscreen(dst_pix) ||
+               (DRI2CanFlip(draw) && pNv->has_pageflip)) &&
+               dst_pix->drawable.width == src_pix->drawable.width &&
+               dst_pix->drawable.height == src_pix->drawable.height &&
+               dst_pix->drawable.depth == src_pix->drawable.depth &&
+               dst_pix->devKind == src_pix->devKind;
+}
+
+static Bool
 can_sync_to_vblank(DrawablePtr draw)
 {
        ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum];
@@ -183,9 +197,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
        struct nouveau_bo *dst_bo = nouveau_pixmap_bo(dst_pix);
        struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix);
        struct nouveau_channel *chan = pNv->chan;
-       BoxRec box = { 0, 0, draw->width, draw->height };
-       RegionRec region;
-       int ret;
+       int type, ret;
 
        /* Throttle on the previous frame before swapping */
        nouveau_bo_map(dst_bo, NOUVEAU_BO_RD);
@@ -209,12 +221,40 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int 
frame,
                FIRE_RING(chan);
        }
 
+       if (can_exchange(draw, dst_pix, src_pix)) {
+               type = DRI2_EXCHANGE_COMPLETE;
 
-       RegionInit(&region, &box, 0);
-       nouveau_dri2_copy_region(draw, &region, s->dst, s->src);
+               if (DRI2CanFlip(draw)) {
+                       type = DRI2_FLIP_COMPLETE;
+                       ret = drmmode_page_flip(draw, src_pix, s);
+                       if (!ret)
+                               goto out;
+               }
+
+               SWAP(s->dst->name, s->src->name);
+               SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo);
+
+       } else {
+               BoxRec box = { 0, 0, draw->width, draw->height };
+               RegionRec region;
+
+               RegionInit(&region, &box, 0);
+
+               type = DRI2_BLIT_COMPLETE;
+               nouveau_dri2_copy_region(draw, &region, s->dst, s->src);
+       }
 
+       /*
+        * Tell the X server buffers are already swapped even if they're
+        * not, to prevent it from blocking the client on the next
+        * GetBuffers request (and let the client do triple-buffering).
+        *
+        * XXX - The DRI2SwapLimit() API will allow us to move this to
+        *       the flip handler with no FPS hit.
+        */
        DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec,
-                        DRI2_BLIT_COMPLETE, s->func, s->data);
+                        type, s->func, s->data);
+out:
        free(s);
 }
 
diff --git a/src/nouveau_local.h b/src/nouveau_local.h
index 5d3200a..38b861f 100644
--- a/src/nouveau_local.h
+++ b/src/nouveau_local.h
@@ -74,4 +74,10 @@ static inline int round_down_pow2(int x)
        return 1 << log2i(x);
 }
 
+#define SWAP(x, y) do {                        \
+               typeof(x) __z = (x);    \
+               (x) = (y);              \
+               (y) = __z;              \
+       } while (0)
+
 #endif
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 5ef7984..fad7d6a 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -28,6 +28,7 @@
 #include "xf86int10.h"
 #include "xf86drm.h"
 #include "xf86drmMode.h"
+#include "nouveau_drm.h"
 
 /*
  * Forward definitions for the functions that make up the driver.
@@ -586,6 +587,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
        struct nouveau_device *dev;
        NVPtr pNv;
        MessageType from;
+       uint64_t v;
        int ret, i;
 
        if (flags & PROBE_DETECT) {
@@ -792,6 +794,15 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
                           pNv->glx_vblank ? "enabled" : "disabled");
        }
 
+#ifdef NOUVEAU_GETPARAM_HAS_PAGEFLIP
+       ret = nouveau_device_get_param(pNv->dev,
+                                      NOUVEAU_GETPARAM_HAS_PAGEFLIP, &v);
+       if (!ret)
+               pNv->has_pageflip = v;
+#else
+       (void)v;
+#endif
+
        if(xf86GetOptValInteger(pNv->Options, OPTION_VIDEO_KEY, 
&(pNv->videoKey))) {
                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 
0x%x\n",
                                        pNv->videoKey);
diff --git a/src/nv_proto.h b/src/nv_proto.h
index ba234b3..8514af9 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -7,6 +7,7 @@ void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y, int 
flags);
 void drmmode_remove_fb(ScrnInfoPtr pScrn);
 Bool drmmode_cursor_init(ScreenPtr pScreen);
 void drmmode_fbcon_copy(ScreenPtr pScreen);
+Bool drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv);
 void drmmode_screen_init(ScreenPtr pScreen);
 void drmmode_screen_fini(ScreenPtr pScreen);
 
diff --git a/src/nv_type.h b/src/nv_type.h
index a9c693f..94c385a 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -51,6 +51,7 @@ typedef struct _NVRec {
     Bool               wfb_enabled;
     Bool               tiled_scanout;
     Bool               glx_vblank;
+    Bool               has_pageflip;
     ScreenBlockHandlerProcPtr BlockHandler;
     CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr  CloseScreen;

commit c88f13e25b0040c1dd0f93e0ac40f62a6005ce59
Author: Francisco Jerez <curroje...@riseup.net>
Date:   Thu Oct 14 22:25:50 2010 +0200

    Allocate a tiled scanout on pre-nv50 too.
    
    Pageflip between tiled and non-tiled surfaces isn't such a good idea.


-- 
To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: http://lists.debian.org/e1psx4u-00050i...@alioth.debian.org

Reply via email to