Merge branch 'ubuntu'
authorXavier Boudet <x-boudet@ti.com>
Tue, 17 Jul 2012 08:21:08 +0000 (10:21 +0200)
committerXavier Boudet <x-boudet@ti.com>
Tue, 17 Jul 2012 08:21:08 +0000 (10:21 +0200)
Conflicts:
debian/changelog
debian/patches/series

debian/changelog
debian/control
debian/patches/0001-add-dri2video.patch [new file with mode: 0644]
debian/patches/1001-xfree86-modes-Let-the-driver-handle-the-transform.patch [new file with mode: 0644]
debian/patches/1002-xfree86-modes-Make-cursor-position-transform-a-helpe.patch [new file with mode: 0644]
debian/patches/series

index eefd6271e0230702a3bee2273ee6768665dee968..661760dbd8e44ba4c29eb520c5d2c0f3afaefdab 100644 (file)
@@ -112,6 +112,12 @@ xorg-server (2:1.11.4-0ubuntu7) precise; urgency=low
 
  -- Ricardo Salveti de Araujo <ricardo.salveti@linaro.org>  Tue, 20 Mar 2012 02:09:18 -0300
 
+xorg-server (2:1.11.4-0ubuntu6+ti1.0) precise; urgency=low
+
+  * Rebased dri2video support on 0ubuntu6
+
+ -- Xavier Boudet <x-boudet@ti.com>  Thu, 15 Mar 2012 11:18:25 +0000
+
 xorg-server (2:1.11.4-0ubuntu6) precise; urgency=low
 
   * debian/patches/500_pointer_barrier_thresholds.diff:
@@ -147,6 +153,12 @@ xorg-server (2:1.11.4-0ubuntu5) precise; urgency=low
 
  -- Chase Douglas <chase.douglas@ubuntu.com>  Wed, 07 Mar 2012 15:36:20 -0800
 
+xorg-server (2:1.11.4-0ubuntu4+ti1.0) precise; urgency=low
+
+  * Rebased dri2video support on 0ubuntu4 patch
+
+ -- David Bercovitz <d-bercovitz@ti.com>  Fri, 02 Mar 2012 12:59:02 +0000
+
 xorg-server (2:1.11.4-0ubuntu4) precise; urgency=low
 
   * debian/patches/500_pointer_barrier_thresholds.diff:
@@ -156,6 +168,12 @@ xorg-server (2:1.11.4-0ubuntu4) precise; urgency=low
 
  -- Christopher James Halse Rogers <raof@ubuntu.com>  Tue, 21 Feb 2012 17:04:41 +1100
 
+xorg-server (2:1.11.4-0ubuntu3+ti1.0) precise; urgency=low
+
+  * Added dri2video support
+
+ -- David Bercovitz <d-bercovitz@ti.com>  Wed, 22 Feb 2012 16:43:17 +0100
+
 xorg-server (2:1.11.4-0ubuntu3) precise; urgency=low
 
   * Fix touch class memory corruption
index 04363fdaa93f14b076a20007c4a2fe87e89645be..5d714bb156607855fd97f45995ba9dda5bad8583 100644 (file)
@@ -42,7 +42,7 @@ Build-Depends:
  xtrans-dev (>= 1.2.2),
  libxau-dev (>= 1:1.0.5-2),
  x11proto-input-dev (>= 2.1.99.6),
- x11proto-dri2-dev (>= 2.6),
+ x11proto-dri2-dev (>= 2.6-2ubuntu1+ti1.1),
  libxdmcp-dev (>= 1:0.99.1),
  libxfont-dev (>= 1:1.4.2),
  libxkbfile-dev (>= 1:0.99.1),
@@ -55,7 +55,8 @@ Build-Depends:
  libudev-dev (>= 151-3),
  libselinux1-dev (>= 2.0.80),
  x11proto-xf86dri-dev (>= 2.1.0),
- libdrm-dev (>= 2.4.3) [!hurd-i386],
+ libdrm-dev (>= 2.4.30-1ubuntu1+ti1.0) [!hurd-i386],
+ libdri2-dev (>= 1.0.2-0ubuntu2), 
  x11proto-gl-dev (>= 1.4.14),
  mesa-common-dev (>= 7.10.3-0ubuntu1),
  libgl1-mesa-dev (>= 7.8),
diff --git a/debian/patches/0001-add-dri2video.patch b/debian/patches/0001-add-dri2video.patch
new file mode 100644 (file)
index 0000000..7922f66
--- /dev/null
@@ -0,0 +1,1182 @@
+From 1301542b17a9ea3cc185e24a3e40d33daa66e8ce Mon Sep 17 00:00:00 2001
+From: Rob Clark <rob@ti.com>
+Date: Tue, 15 Nov 2011 14:28:06 -0600
+Subject: [PATCH] add dri2video
+
+TODO:
+ + implement OSD support.. core should register damage and automatically
+   re-call ScheduleSwapVid..
+ + automatically re-call ScheduleSwapVid on dri2 drawable resize...
+---
+ hw/xfree86/dri2/dri2.c    |  364 +++++++++++++++++++++++++++++++++++++--------
+ hw/xfree86/dri2/dri2.h    |  127 ++++++++++++++++-
+ hw/xfree86/dri2/dri2ext.c |  214 +++++++++++++++++++++++++-
+ 3 files changed, 632 insertions(+), 73 deletions(-)
+
+Index: xserver/hw/xfree86/dri2/dri2.c
+===================================================================
+--- xserver.orig/hw/xfree86/dri2/dri2.c        2012-02-22 11:04:26.000000000 +0100
++++ xserver/hw/xfree86/dri2/dri2.c     2012-02-22 16:32:28.000000000 +0100
+@@ -91,6 +91,8 @@
+     int                                refcnt;
+     unsigned int               numDrivers;
+     const char                        **driverNames;
++    unsigned int               numFormats;
++    unsigned int              *formats;
+     const char                        *deviceName;
+     int                                fd;
+     unsigned int               lastSequence;
+@@ -102,12 +104,29 @@
+     DRI2GetMSCProcPtr          GetMSC;
+     DRI2ScheduleWaitMSCProcPtr         ScheduleWaitMSC;
+     DRI2AuthMagicProcPtr       AuthMagic;
++    DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
++    DRI2SwapLimitValidateProcPtr SwapLimitValidate;
++    DRI2GetExtraBufferNamesProcPtr GetExtraBufferNames;
++    DRI2CreateBufferVidProcPtr  CreateBufferVid;
++    DRI2ScheduleSwapVidProcPtr  ScheduleSwapVid;
++    DRI2SetAttributeProcPtr     SetAttribute;
++    DRI2GetAttributeProcPtr     GetAttribute;
+     HandleExposuresProcPtr       HandleExposures;
+     ConfigNotifyProcPtr                ConfigNotify;
+ } DRI2ScreenRec;
++static Bool
++supports_video(DRI2ScreenPtr ds)
++{
++    /* it would be easier if we had a way to track the driverType in the
++     * DRI2DrawablePtr.. but the DRI2DrawablePtr isn't created at the
++     * time of DRI2Connect()..
++     */
++    return ds && ds->numFormats && ds->CreateBufferVid && ds->ScheduleSwapVid;
++}
++
+ static DRI2ScreenPtr
+ DRI2GetScreen(ScreenPtr pScreen)
+ {
+@@ -179,6 +198,7 @@
+     pPriv->last_swap_ust = 0;
+     list_init(&pPriv->reference_list);
+     pPriv->serialNumber = DRI2DrawableSerial(pDraw);
++    pPriv->needInvalidate = FALSE;
+     if (pDraw->type == DRAWABLE_WINDOW) {
+       pWin = (WindowPtr) pDraw;
+@@ -191,6 +211,35 @@
+     return pPriv;
+ }
++Bool
++DRI2SwapLimit(DrawablePtr pDraw, int swap_limit)
++{
++    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
++    DRI2ScreenPtr ds;
++    if (!pPriv)
++      return FALSE;
++
++    ds = pPriv->dri2_screen;
++
++    if (!ds->SwapLimitValidate
++      || !ds->SwapLimitValidate(pDraw, swap_limit))
++      return FALSE;
++
++    pPriv->swap_limit = swap_limit;
++
++    /* Check throttling */
++    if (pPriv->swapsPending >= pPriv->swap_limit)
++      return TRUE;
++
++    if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) {
++      if (pPriv->blockedClient) {
++          AttendClient(pPriv->blockedClient);
++          pPriv->blockedClient = NULL;
++      }
++    }
++
++    return TRUE;
++}
+ typedef struct DRI2DrawableRefRec {
+     XID                 id;
+     XID                 dri2_id;
+@@ -264,15 +313,26 @@
+     return Success;
+ }
++static void destroy_buffers(DrawablePtr pDraw, DRI2BufferPtr *buffers, int count)
++{
++    if (buffers != NULL) {
++      DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
++      int i;
++      for (i = 0; i < count; i++)
++          if (buffers[i])
++              (*ds->DestroyBuffer)(pDraw, buffers[i]);
++
++      free(buffers);
++    }
++}
++
+ static int DRI2DrawableGone(pointer p, XID id)
+ {
+     DRI2DrawablePtr pPriv = p;
+-    DRI2ScreenPtr   ds = pPriv->dri2_screen;
+     DRI2DrawableRefPtr ref, next;
+     WindowPtr pWin;
+     PixmapPtr pPixmap;
+     DrawablePtr pDraw;
+-    int i;
+     list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
+       if (ref->dri2_id == id) {
+@@ -304,12 +364,7 @@
+       dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
+     }
+-    if (pPriv->buffers != NULL) {
+-      for (i = 0; i < pPriv->bufferCount; i++)
+-          (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+-
+-      free(pPriv->buffers);
+-    }
++    destroy_buffers(pDraw, pPriv->buffers, pPriv->bufferCount);
+     free(pPriv);
+@@ -317,7 +372,7 @@
+ }
+ static int
+-find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
++find_attachment(DRI2DrawablePtr pPriv, unsigned attachment, DRI2BufferPtr *buf)
+ {
+     int i;
+@@ -328,6 +383,8 @@
+     for (i = 0; i < pPriv->bufferCount; i++) {
+       if ((pPriv->buffers[i] != NULL)
+           && (pPriv->buffers[i]->attachment == attachment)) {
++          if (buf)
++              *buf = pPriv->buffers[i];
+           return i;
+       }
+     }
+@@ -336,14 +393,27 @@
+ }
+ static Bool
++valid_format(DRI2ScreenPtr ds, unsigned int format)
++{
++    int i;
++    for (i = 0; i < ds->numFormats; i++) {
++      if (format == ds->formats[i]) {
++          return TRUE;
++      }
++    }
++    return FALSE;
++}
++
++static Bool
+ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
+                        DRI2DrawablePtr pPriv,
+                        unsigned int attachment, unsigned int format,
+                        int dimensions_match, DRI2BufferPtr *buffer)
+ {
+-    int old_buf = find_attachment(pPriv, attachment);
++    int old_buf = find_attachment(pPriv, attachment, NULL);
+     if ((old_buf < 0)
++      || attachment == DRI2BufferFrontLeft
+       || !dimensions_match
+       || (pPriv->buffers[old_buf]->format != format)) {
+       *buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
+@@ -352,6 +422,8 @@
+     } else {
+       *buffer = pPriv->buffers[old_buf];
++      if (ds->ReuseBufferNotify)
++              (*ds->ReuseBufferNotify)(pDraw, *buffer);
+       pPriv->buffers[old_buf] = NULL;
+       return FALSE;
+     }
+@@ -361,18 +433,7 @@
+ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
+                            DRI2BufferPtr *buffers, int out_count, int *width, int *height)
+ {
+-    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+-    int i;
+-
+-    if (pPriv->buffers != NULL) {
+-      for (i = 0; i < pPriv->bufferCount; i++) {
+-          if (pPriv->buffers[i] != NULL) {
+-              (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+-          }
+-      }
+-
+-      free(pPriv->buffers);
+-    }
++    destroy_buffers(pDraw, pPriv->buffers, pPriv->bufferCount);
+     pPriv->buffers = buffers;
+     pPriv->bufferCount = out_count;
+@@ -417,6 +478,15 @@
+       const unsigned attachment = *(attachments++);
+       const unsigned format = (has_format) ? *(attachments++) : 0;
++      /* note: don't require a valid format for old drivers which don't
++       * register their supported formats..
++       */
++      if (has_format && (ds->numFormats > 0) && !valid_format(ds, format)) {
++          xf86DrvMsg(pDraw->pScreen->myNum, X_ERROR,
++                  "[DRI2] %s: bad format: %d\n", __func__, format);
++          goto err_out;
++      }
++
+       if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
+                                    format, dimensions_match,
+                                    &buffers[i]))
+@@ -506,19 +576,11 @@
+     *out_count = 0;
+-    if (buffers) {
+-      for (i = 0; i < count; i++) {
+-          if (buffers[i] != NULL)
+-              (*ds->DestroyBuffer)(pDraw, buffers[i]);
+-      }
++    destroy_buffers(pDraw, buffers, count);
+-      free(buffers);
+-      buffers = NULL;
+-    }
++    update_dri2_drawable_buffers(pPriv, pDraw, NULL, *out_count, width, height);
+-    update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width, height);
+-
+-    return buffers;
++    return NULL;
+ }
+ DRI2BufferPtr *
+@@ -537,6 +599,95 @@
+                         out_count, TRUE);
+ }
++DRI2BufferPtr *
++DRI2GetBuffersVid(DrawablePtr pDraw, int width, int height,
++      unsigned int *attachments, int count, int *out_count)
++{
++    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
++    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
++    DRI2BufferPtr  *buffers;
++    int i, n = 0;
++
++    if (!pPriv || !supports_video(ds)) {
++      *out_count = 0;
++      return NULL;
++    }
++
++    buffers = calloc(count, sizeof(buffers[0]));
++    if (!buffers)
++      goto err_out;
++
++    for (i = 0; i < count; i++) {
++      DRI2BufferPtr buf;
++      const unsigned attachment = *(attachments++);
++      const unsigned format = *(attachments++);
++
++      /* grow array of stored buffers if needed: */
++      if (attachment >= pPriv->bufferCount) {
++          int n = attachment + 1;
++          DRI2BufferPtr *newBuffers = realloc(pPriv->buffers,
++                  sizeof(pPriv->buffers[0]) * n);
++          if (!newBuffers) {
++              xf86DrvMsg(pDraw->pScreen->myNum, X_ERROR,
++                      "[DRI2] %s: allocation failed for buffer: %d\n",
++                      __func__, attachment);
++              goto err_out;
++          }
++          pPriv->buffers = newBuffers;
++          memset(&pPriv->buffers[pPriv->bufferCount], 0,
++                  (n - pPriv->bufferCount) * sizeof(pPriv->buffers[0]));
++          pPriv->bufferCount = n;
++      }
++
++      /* destroy any previous buffer at this attachment slot */
++      if (pPriv->buffers[attachment]) {
++          (*ds->DestroyBuffer)(pDraw, pPriv->buffers[attachment]);
++          pPriv->buffers[attachment] = NULL;
++      }
++
++      if ((width == 0) && (height == 0)) {
++          /* client just wanted us to delete the buffer */
++          continue;
++      }
++
++      if (!valid_format(ds, format)) {
++          xf86DrvMsg(pDraw->pScreen->myNum, X_ERROR,
++                  "[DRI2] %s: bad format: %d\n", __func__, format);
++          goto err_out;
++      }
++
++      if (attachment == DRI2BufferFrontLeft) {
++          buf = (*ds->CreateBuffer)(pDraw, attachment, format);
++          /* note: don't expose front buffer to client */
++      } else {
++          buf = (*ds->CreateBufferVid)(pDraw, attachment, format, width, height);
++          buffers[n++] = buf;
++      }
++
++      if (! buf) {
++          goto err_out;
++      }
++
++      pPriv->buffers[attachment] = buf;
++    }
++
++    *out_count = n;
++
++    return buffers;
++
++err_out:
++
++    *out_count = 0;
++
++    for (i = 0; i < n; i++)
++      if (buffers[i])
++          pPriv->buffers[buffers[i]->attachment] = NULL;
++
++    destroy_buffers(pDraw, buffers, n);
++
++    return NULL;
++}
++
+ static void
+ DRI2InvalidateDrawable(DrawablePtr pDraw)
+ {
+@@ -549,7 +700,7 @@
+     pPriv->needInvalidate = FALSE;
+     list_for_each_entry(ref, &pPriv->reference_list, link)
+-      ref->invalidate(pDraw, ref->priv);
++      ref->invalidate(pDraw, ref->priv, ref->id);
+ }
+ /*
+@@ -609,22 +760,14 @@
+ {
+     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+     DRI2DrawablePtr pPriv;
+-    DRI2BufferPtr   pDestBuffer, pSrcBuffer;
+-    int                   i;
++    DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
+     pPriv = DRI2GetDrawable(pDraw);
+     if (pPriv == NULL)
+       return BadDrawable;
+-    pDestBuffer = NULL;
+-    pSrcBuffer = NULL;
+-    for (i = 0; i < pPriv->bufferCount; i++)
+-    {
+-      if (pPriv->buffers[i]->attachment == dest)
+-          pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+-      if (pPriv->buffers[i]->attachment == src)
+-          pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+-    }
++    find_attachment(pPriv, dest, &pDestBuffer);
++    find_attachment(pPriv, src, &pSrcBuffer);
+     if (pSrcBuffer == NULL || pDestBuffer == NULL)
+       return BadValue;
+@@ -792,31 +935,41 @@
+     return FALSE;
+ }
+-int
+-DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+-              CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+-              DRI2SwapEventPtr func, void *data)
++/*
++ * A TraverseTree callback to invalidate all windows using the same
++ * pixmap
++ */
++static int
++DRI2InvalidateWalk(WindowPtr pWin, pointer data)
++{
++    if (pWin->drawable.pScreen->GetWindowPixmap(pWin) != data)
++      return WT_DONTWALKCHILDREN;
++    DRI2InvalidateDrawable(&pWin->drawable);
++    return WT_WALKCHILDREN;
++}
++
++static int
++swap_buffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
++           CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
++           DRI2SwapEventPtr func, void *data,
++           Bool vid, unsigned int source, BoxPtr b)
+ {
+     ScreenPtr       pScreen = pDraw->pScreen;
+     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+-    DRI2DrawablePtr pPriv;
++    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+     DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
+-    int             ret, i;
++    int             ret;
+     CARD64          ust, current_msc;
+-    pPriv = DRI2GetDrawable(pDraw);
+-    if (pPriv == NULL) {
++    if ((pPriv == NULL) || (vid && !supports_video(ds))) {
+         xf86DrvMsg(pScreen->myNum, X_ERROR,
+                  "[DRI2] %s: bad drawable\n", __func__);
+       return BadDrawable;
+     }
+-    for (i = 0; i < pPriv->bufferCount; i++) {
+-      if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
+-          pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+-      if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
+-          pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+-    }
++    find_attachment(pPriv, DRI2BufferFrontLeft, &pDestBuffer);
++    find_attachment(pPriv, source, &pSrcBuffer);
++
+     if (pSrcBuffer == NULL || pDestBuffer == NULL) {
+         xf86DrvMsg(pScreen->myNum, X_ERROR,
+                  "[DRI2] %s: drawable has no back or front?\n", __func__);
+@@ -824,7 +977,7 @@
+     }
+     /* Old DDX or no swap interval, just blit */
+-    if (!ds->ScheduleSwap || !pPriv->swap_interval) {
++    if ((!ds->ScheduleSwap || !pPriv->swap_interval) && !vid) {
+       BoxRec box;
+       RegionRec region;
+@@ -860,7 +1013,6 @@
+           if (current_msc < pPriv->last_swap_target)
+               pPriv->last_swap_target = current_msc;
+-
+       }
+       /*
+@@ -876,8 +1028,14 @@
+     }
+     pPriv->swapsPending++;
+-    ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
+-                            swap_target, divisor, remainder, func, data);
++    if (vid) {
++      DrawablePtr osd = NULL;  // TODO
++      ret = (*ds->ScheduleSwapVid)(client, pDraw, pDestBuffer, pSrcBuffer,
++              b, osd, swap_target, divisor, remainder, func, data);
++    } else {
++      ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
++              swap_target, divisor, remainder, func, data);
++    }
+     if (!ret) {
+       pPriv->swapsPending--; /* didn't schedule */
+         xf86DrvMsg(pScreen->myNum, X_ERROR,
+@@ -892,11 +1050,50 @@
+      */
+     *swap_target = pPriv->swap_count + pPriv->swapsPending;
++    if (vid) {
++      return Success;
++    }
++
++    if (pDraw->type == DRAWABLE_WINDOW) {
++      WindowPtr       pWin = (WindowPtr) pDraw;
++      PixmapPtr       pPixmap = pScreen->GetWindowPixmap(pWin);
++
++      /*
++       * Find the top-most window using this pixmap
++       */
++      while (pWin->parent && pScreen->GetWindowPixmap(pWin->parent) == pPixmap)
++          pWin = pWin->parent;
++
++      /*
++       * Walk the sub-tree to invalidate all of the
++       * windows using the same pixmap
++       */
++      TraverseTree(pWin, DRI2InvalidateWalk, pPixmap);
++      DRI2InvalidateDrawable(&pPixmap->drawable);
++    } else
+     DRI2InvalidateDrawable(pDraw);
+     return Success;
+ }
++int
++DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
++              CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
++              DRI2SwapEventPtr func, void *data)
++{
++    return swap_buffers(client, pDraw, target_msc, divisor, remainder,
++          swap_target, func, data, FALSE, DRI2BufferBackLeft, NULL);
++}
++
++int
++DRI2SwapBuffersVid(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
++              CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
++              unsigned int source, BoxPtr b, DRI2SwapEventPtr func, void *data)
++{
++    return swap_buffers(client, pDraw, target_msc, divisor, remainder,
++          swap_target, func, data, TRUE, source, b);
++}
++
+ void
+ DRI2SwapInterval(DrawablePtr pDrawable, int interval)
+ {
+@@ -1014,6 +1211,77 @@
+     return ds->ScheduleSwap && ds->GetMSC;
+ }
++#define ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
++
++/* length in multiple of CARD32's, passed in value should be copied by
++ * receiver
++ */
++int
++DRI2SetAttribute(DrawablePtr pDraw, Atom attribute, int len, const CARD32 *val)
++{
++    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
++    int ret = BadMatch;
++
++    if (!supports_video(ds)) {
++      return BadDrawable;
++    }
++
++    if (attribute == ATOM("XV_OSD")) {
++    } else if (ds->SetAttribute) {
++      ret = (*ds->SetAttribute)(pDraw, attribute, len, val);
++    }
++
++    return ret;
++}
++
++/* length in multiple of CARD32's, returned val should *not* be free'd
++ * (unlike similar function on client side) to avoid temporary allocation
++ * and extra copy.
++ */
++int
++DRI2GetAttribute(DrawablePtr pDraw, Atom attribute, int *len, const CARD32 **val)
++{
++    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
++    int ret = BadMatch;
++
++    if (!supports_video(ds)) {
++      return BadDrawable;
++    }
++
++    if (attribute == ATOM("XV_OSD")) {
++    } else if (ds->GetAttribute) {
++      ret = (*ds->GetAttribute)(pDraw, attribute, len, val);
++    }
++
++    return ret;
++}
++
++int
++DRI2GetFormats(ScreenPtr pScreen, unsigned int *nformats, unsigned int **formats)
++{
++    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
++
++    if (! supports_video(ds)) {
++      return BadDrawable;
++    }
++
++    *nformats = ds->numFormats;
++    *formats  = ds->formats;
++
++    return Success;
++}
++
++unsigned int
++DRI2GetExtraBufferNames(DrawablePtr pDraw, DRI2BufferPtr buf,
++      unsigned int **names, unsigned int **pitches)
++{
++    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
++    if (ds->GetExtraBufferNames) {
++      return (*ds->GetExtraBufferNames)(pDraw, buf, names, pitches);
++    }
++    return 0;
++}
++
+ Bool
+ DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
+           const char **driverName, const char **deviceName)
+@@ -1081,9 +1349,10 @@
+     const char* driverTypeNames[] = {
+       "DRI", /* DRI2DriverDRI */
+       "VDPAU", /* DRI2DriverVDPAU */
++      "XV", /* DRI2DriverXV */
+     };
+     unsigned int i;
+-    CARD8 cur_minor;
++    CARD8 cur_minor = 1;
+     if (info->version < 3)
+       return FALSE;
+@@ -1121,14 +1390,45 @@
+       ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
+       ds->GetMSC = info->GetMSC;
+       cur_minor = 3;
+-    } else {
+-      cur_minor = 1;
+     }
+     if (info->version >= 5) {
+         ds->AuthMagic = info->AuthMagic;
+     }
++    if (info->version >= 6) {
++      ds->ReuseBufferNotify = info->ReuseBufferNotify;
++      ds->SwapLimitValidate = info->SwapLimitValidate;
++    }
++
++    if (info->version >= 7) {
++      if ((info->numDrivers > DRI2DriverXV) &&
++              info->driverNames[DRI2DriverXV]) {
++          /* if driver claims to support DRI2DriverXV, then ensure
++           * it provides the required fxn ptrs:
++           */
++          if (!info->CreateBufferVid || !info->ScheduleSwapVid) {
++              xf86DrvMsg(pScreen->myNum, X_WARNING,
++                      "[DRI2] DRI2DriverXV must implement "
++                      "CreateBuffersVid and ScheduleSwapVid.\n");
++              goto err_out;
++          }
++      }
++      ds->numFormats = info->numFormats;
++      ds->formats = malloc(info->numFormats * sizeof(*ds->formats));
++      if (!ds->formats)
++          goto err_out;
++      memcpy(ds->formats, info->formats,
++              info->numFormats * sizeof(*ds->formats));
++      ds->GetExtraBufferNames = info->GetExtraBufferNames;
++      ds->CreateBufferVid = info->CreateBufferVid;
++      ds->ScheduleSwapVid = info->ScheduleSwapVid;
++      ds->SetAttribute = info->SetAttribute;
++      ds->GetAttribute = info->GetAttribute;
++
++      cur_minor = 4;
++    }
++
+     /*
+      * if the driver doesn't provide an AuthMagic function or the info struct
+      * version is too low, it relies on the old method (using libdrm) or fail
+@@ -1178,6 +1478,10 @@
+ err_out:
+     xf86DrvMsg(pScreen->myNum, X_WARNING,
+             "[DRI2] Initialization failed for info version %d.\n", info->version);
++    if (ds) {
++      free(ds->formats);
++      free(ds->driverNames);
++    }
+     free(ds);
+     return FALSE;
+ }
+Index: xserver/hw/xfree86/dri2/dri2.h
+===================================================================
+--- xserver.orig/hw/xfree86/dri2/dri2.h        2012-02-22 11:04:26.000000000 +0100
++++ xserver/hw/xfree86/dri2/dri2.h     2012-02-22 16:31:43.000000000 +0100
+@@ -104,12 +104,73 @@
+                                                  CARD64 remainder,
+                                                  DRI2SwapEventPtr func,
+                                                  void *data);
++
++/**
++ * Schedule a video buffer swap
++ *
++ * Drivers should queue an event for the frame count that satisfies the
++ * parameters passed in.  If the event is in the future (i.e. the conditions
++ * aren't currently satisfied), the server may block the client at the next
++ * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
++ * \c DRI2SwapComplete, which will handle waking the client and returning
++ * the appropriate data.
++ *
++ * The DDX is responsible for doing an overlay buffer flip/exchange, or
++ * scaling/colorconvert blit when the corresponding event arrives.
++ *
++ * If the target drawable is resized/damaged, or the osd pixmap is changed/
++ * damaged, ScheduleSwapVid can be re-invoked by the core with the same
++ * source buffer to repair the dri2 video drawable.
++ * XXX TODO this part isn't implemented in core yet..
++ *
++ * \param client client pointer (used for block/unblock)
++ * \param pDraw drawable whose count we want
++ * \param pDestBuffer current front buffer
++ * \param pSrcBuffer current back buffer
++ * \param b the crop box
++ * \param osd the on-screen-display overlay pixmap, should be an ARGB pixmap
++ *   that is blended on top of the video as part of swap.  Multiple layers
++ *   to blend over the video should be flattened into a single layer by the
++ *   client
++ * \param target_msc frame count to wait for
++ * \param divisor divisor for condition equation
++ * \param remainder remainder for division equation
++ * \param func function to call when the swap completes
++ * \param data data for the callback \p func.
++ */
++typedef int           (*DRI2ScheduleSwapVidProcPtr)(ClientPtr client,
++                                                 DrawablePtr pDraw,
++                                                 DRI2BufferPtr pDestBuffer,
++                                                 DRI2BufferPtr pSrcBuffer,
++                                                 BoxPtr b,
++                                                 DrawablePtr osd,
++                                                 CARD64 *target_msc,
++                                                 CARD64 divisor,
++                                                 CARD64 remainder,
++                                                 DRI2SwapEventPtr func,
++                                                 void *data);
++
+ typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
+                                                  unsigned int attachment,
+                                                  unsigned int format);
++typedef DRI2BufferPtr (*DRI2CreateBufferVidProcPtr)(DrawablePtr pDraw,
++                                                 unsigned int attachment,
++                                                 unsigned int format,
++                                                 unsigned int width,
++                                                 unsigned int height);
+ typedef void          (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
+                                                   DRI2BufferPtr buffer);
+ /**
++ * Notifies driver when DRI2GetBuffers reuses a dri2 buffer.
++ *
++ * Driver may rename the dri2 buffer in this notify if it is required.
++ *
++ * \param pDraw drawable whose count we want
++ * \param buffer buffer that will be returned to client
++ */
++typedef void          (*DRI2ReuseBufferNotifyProcPtr)(DrawablePtr pDraw,
++                                                    DRI2BufferPtr buffer);
++/**
+  * Get current media stamp counter values
+  *
+  * This callback is used to support the SGI_video_sync and OML_sync_control
+@@ -156,12 +217,62 @@
+                                                     CARD64 remainder);
+ typedef void          (*DRI2InvalidateProcPtr)(DrawablePtr pDraw,
+-                                               void *data);
++                                               void *data,
++                                               XID id);
++
++/**
++ * DRI2 calls this hook when ever swap_limit is going to be changed. Default
++ * implementation for the hook only accepts one as swap_limit. If driver can
++ * support other swap_limits it has to implement supported limits with this
++ * callback.
++ *
++ * \param pDraw drawable whos swap_limit is going to be changed
++ * \param swap_limit new swap_limit that going to be set
++ * \return TRUE if limit is support, FALSE if not.
++ */
++typedef Bool          (*DRI2SwapLimitValidateProcPtr)(DrawablePtr pDraw,
++                                                      int swap_limit);
++
++
++/**
++ * An ugly approach to avoid changing DRI2BufferPtr and cause ABI breakage
++ * between driver and xserver.  This only needs to be implemented by drivers
++ * supporting planar formats with one buffer per plane.
++ *
++ * This might be a good argument for having drivers in-tree ;-)
++ *
++ * \param pDraw drawable that the buffer belongs to
++ * \param buf the DRI2 buffer
++ * \param names array of buffer names
++ * \param pitches array of buffer pitches
++ * \return the number of additional buffers, ie. for I420 tri-planar buffer,
++ * if represented as multiple buffer names, the Y buffer name would be in
++ * buf->name, this function would return 2, and return the U and V buffer
++ * names by reference.
++ */
++typedef unsigned int  (*DRI2GetExtraBufferNamesProcPtr)(DrawablePtr pDraw,
++      DRI2BufferPtr buf, unsigned int **names, unsigned int **pitches);
++
++/**
++ * Length in multiple of CARD32's, passed in value should be copied by
++ * receiver
++ */
++typedef int (*DRI2SetAttributeProcPtr)(DrawablePtr pDraw, Atom attribute,
++      int len, const CARD32 *val);
++
++/**
++ * Length in multiple of CARD32's, returned val should *not* be free'd
++ * (unlike similar function on client side) to avoid temporary allocation
++ * and extra copy.
++ */
++typedef int (*DRI2GetAttributeProcPtr)(DrawablePtr pDraw, Atom attribute,
++      int *len, const CARD32 **val);
++
+ /**
+  * Version of the DRI2InfoRec structure defined in this header
+  */
+-#define DRI2INFOREC_VERSION 5
++#define DRI2INFOREC_VERSION 7
+ typedef struct {
+     unsigned int version;     /**< Version of this struct */
+@@ -189,6 +300,20 @@
+     /* added in version 5 */
+     DRI2AuthMagicProcPtr      AuthMagic;
++    /* added in version 6 */
++
++    DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
++    DRI2SwapLimitValidateProcPtr SwapLimitValidate;
++
++    /* added in version 7 */
++
++    unsigned int numFormats;
++    const unsigned int *formats;
++    DRI2GetExtraBufferNamesProcPtr GetExtraBufferNames;
++    DRI2CreateBufferVidProcPtr        CreateBufferVid;
++    DRI2ScheduleSwapVidProcPtr        ScheduleSwapVid;
++    DRI2SetAttributeProcPtr   SetAttribute;
++    DRI2GetAttributeProcPtr   GetAttribute;
+ }  DRI2InfoRec, *DRI2InfoPtr;
+ extern _X_EXPORT int DRI2EventBase;
+@@ -250,11 +375,19 @@
+       int *width, int *height, unsigned int *attachments, int count,
+       int *out_count);
++extern _X_EXPORT DRI2BufferPtr * DRI2GetBuffersVid(DrawablePtr pDraw,
++      int width, int height, unsigned int *attachments, int count,
++      int *out_count);
++
+ extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
++extern _X_EXPORT Bool DRI2SwapLimit(DrawablePtr pDraw, int swap_limit);
+ extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
+                                    CARD64 target_msc, CARD64 divisor,
+                                    CARD64 remainder, CARD64 *swap_target,
+                                    DRI2SwapEventPtr func, void *data);
++extern _X_EXPORT int DRI2SwapBuffersVid(ClientPtr client, DrawablePtr pDraw,
++      CARD64 target_msc, CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
++      unsigned int source, BoxPtr b, DRI2SwapEventPtr func, void *data);
+ extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
+ extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
+@@ -284,4 +417,22 @@
+                                         int frame, unsigned int tv_sec,
+                                         unsigned int tv_usec);
++extern _X_EXPORT int DRI2SetAttribute(DrawablePtr pDraw, Atom attribute,
++      int len, const CARD32 *val);
++extern _X_EXPORT int DRI2GetAttribute(DrawablePtr pDraw, Atom attribute,
++      int *len, const CARD32 **val);
++extern _X_EXPORT int DRI2GetFormats(ScreenPtr pScreen,
++      unsigned int *nformats, unsigned int **formats);
++
++extern _X_EXPORT unsigned int DRI2GetExtraBufferNames(DrawablePtr pDraw,
++      DRI2BufferPtr buf, unsigned int **names, unsigned int **pitches);
++
++
++/* some utility macros.. maybe could go elsewhere? */
++#define FOURCC(a, b, c, d) (((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )))
++#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
++#ifndef ARRAY_SIZE
++#  define ARRAY_SIZE(_a)   (sizeof((_a)) / sizeof((_a)[0]))
++#endif
++
+ #endif
+Index: xserver/hw/xfree86/dri2/dri2ext.c
+===================================================================
+--- xserver.orig/hw/xfree86/dri2/dri2ext.c     2012-02-22 11:04:26.000000000 +0100
++++ xserver/hw/xfree86/dri2/dri2ext.c  2012-02-22 16:37:21.000000000 +0100
+@@ -78,6 +78,7 @@
+       swaps(&stuff->length, n);
+     REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
++
+     rep.type = X_Reply;
+     rep.length = 0;
+     rep.sequenceNumber = client->sequence;
+@@ -157,7 +158,7 @@
+ }
+ static void
+-DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv)
++DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv, XID id)
+ {
+     xDRI2InvalidateBuffers event;
+     ClientPtr client = priv;
+@@ -206,12 +207,13 @@
+ static int
+-send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
++send_buffers_reply(ClientPtr client, DrawablePtr pDrawable, int vid,
+                  DRI2BufferPtr *buffers, int count, int width, int height)
+ {
+     xDRI2GetBuffersReply rep;
+-    int skip = 0;
+-    int i;
++    int skip = 0, extra = 0;
++    unsigned int *names, *pitches;
++    int i, j;
+     if (buffers == NULL)
+           return BadAlloc;
+@@ -227,8 +229,24 @@
+       }
+     }
++    if (vid) {
++      extra = 4 * (count - skip);
++
++      for (i = 0; i < count; i++) {
++          /* Do not send the real front buffer of a window to the client.
++           */
++          if ((pDrawable->type == DRAWABLE_WINDOW)
++                  && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
++              continue;
++          }
++
++          extra += 8 * DRI2GetExtraBufferNames(pDrawable, buffers[i],
++                  &names, &pitches);
++      }
++    }
++
+     rep.type = X_Reply;
+-    rep.length = (count - skip) * sizeof(xDRI2Buffer) / 4;
++    rep.length = ((count - skip) * sizeof(xDRI2Buffer) + extra) / 4;
+     rep.sequenceNumber = client->sequence;
+     rep.width = width;
+     rep.height = height;
+@@ -251,6 +269,17 @@
+       buffer.cpp = buffers[i]->cpp;
+       buffer.flags = buffers[i]->flags;
+       WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
++
++      if (vid) {
++          CARD32 n = DRI2GetExtraBufferNames(pDrawable, buffers[i],
++                  &names, &pitches);
++          WriteToClient(client, sizeof(n), &n);
++          for (j = 0; j < n; j++) {
++              CARD32 name = names[j], pitch = pitches[j];
++              WriteToClient(client, sizeof(name), &name);
++              WriteToClient(client, sizeof(pitch), &pitch);
++          }
++      }
+     }
+     return Success;
+ }
+@@ -278,8 +307,8 @@
+                            attachments, stuff->count, &count);
+-    return send_buffers_reply(client, pDrawable, buffers, count, width, height);
+-
++    return send_buffers_reply(client, pDrawable, FALSE,
++          buffers, count, width, height);
+ }
+ static int
+@@ -303,7 +332,40 @@
+     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
+                                      attachments, stuff->count, &count);
+-    return send_buffers_reply(client, pDrawable, buffers, count, width, height);
++    return send_buffers_reply(client, pDrawable, FALSE,
++          buffers, count, width, height);
++}
++
++static int
++ProcDRI2GetBuffersVid(ClientPtr client)
++{
++    REQUEST(xDRI2GetBuffersVidReq);
++    DrawablePtr pDrawable;
++    DRI2BufferPtr *buffers;
++    int status, count;
++    unsigned int *attachments;
++
++    REQUEST_FIXED_SIZE(xDRI2GetBuffersVidReq, stuff->count * (2 * 4));
++    if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
++                     &pDrawable, &status))
++      return status;
++
++    if (DRI2ThrottleClient(client, pDrawable))
++      return Success;
++
++    attachments = (unsigned int *) &stuff[1];
++    buffers = DRI2GetBuffersVid(pDrawable, stuff->width, stuff->height,
++                              attachments, stuff->count, &count);
++
++    status = send_buffers_reply(client, pDrawable, TRUE, buffers, count, 0, 0);
++
++    /* note, unlike other DRI2GetBuffers variants, we allow requesting/
++     * returning just a subset of buffers.. so array that is returned is
++     * not the one held in pPriv, so must be free'd
++     */
++    free(buffers);
++
++    return status;
+ }
+ static int
+@@ -416,6 +478,53 @@
+     return Success;
+ }
++static int
++ProcDRI2SwapBuffersVid(ClientPtr client)
++{
++    REQUEST(xDRI2SwapBuffersVidReq);
++    xDRI2SwapBuffersReply rep;
++    DrawablePtr pDrawable;
++    CARD64 target_msc, divisor, remainder, swap_target;
++    BoxRec b;
++    int status;
++
++    REQUEST_SIZE_MATCH(xDRI2SwapBuffersVidReq);
++
++    if (!validDrawable(client, stuff->drawable,
++                     DixReadAccess | DixWriteAccess, &pDrawable, &status))
++      return status;
++
++    /*
++     * Ensures an out of control client can't exhaust our swap queue, and
++     * also orders swaps.
++     */
++    if (DRI2ThrottleClient(client, pDrawable))
++      return Success;
++
++    target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
++    divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
++    remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
++
++    b.x1 = stuff->x1;
++    b.y1 = stuff->y1;
++    b.x2 = stuff->x2;
++    b.y2 = stuff->y2;
++
++    status = DRI2SwapBuffersVid(client, pDrawable, target_msc, divisor, remainder,
++          &swap_target, stuff->source, &b, DRI2SwapEvent, pDrawable);
++    if (status != Success)
++      return BadDrawable;
++
++    rep.type = X_Reply;
++    rep.length = 0;
++    rep.sequenceNumber = client->sequence;
++    load_swap_reply(&rep, swap_target);
++
++    WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
++
++    return Success;
++}
++
+ static void
+ load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc)
+ {
+@@ -539,6 +648,87 @@
+ }
+ static int
++ProcDRI2SetAttribute(ClientPtr client)
++{
++    REQUEST(xDRI2SetAttributeReq);
++    DrawablePtr pDrawable;
++    int status;
++    int len = (stuff->length * 4 - sizeof(xDRI2SetAttributeReq)) / 4;
++
++    REQUEST_FIXED_SIZE(xDRI2SetAttributeReq, len * 4);
++
++    if (!validDrawable(client, stuff->drawable,
++          DixReadAccess | DixWriteAccess, &pDrawable, &status))
++      return status;
++
++    status = DRI2SetAttribute(pDrawable, stuff->attribute, len,
++          (const CARD32 *)&stuff[1]);
++    if (status != Success)
++      return status;
++
++    return Success;
++}
++
++static int
++ProcDRI2GetAttribute(ClientPtr client)
++{
++    REQUEST(xDRI2GetAttributeReq);
++    xDRI2GetAttributeReply rep;
++    DrawablePtr pDrawable;
++    const CARD32 *val;
++    int status, len;
++
++    REQUEST_SIZE_MATCH(xDRI2GetAttributeReq);
++
++    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
++          &status))
++      return status;
++
++    status = DRI2GetAttribute(pDrawable, stuff->attribute, &len, &val);
++    if (status != Success)
++      return status;
++
++    rep.type = X_Reply;
++    rep.length = len;
++    rep.sequenceNumber = client->sequence;
++    WriteToClient(client, sizeof(xDRI2GetAttributeReply), &rep);
++    WriteToClient(client, len * 4, val);
++
++    return Success;
++}
++
++static int
++ProcDRI2GetFormats(ClientPtr client)
++{
++    REQUEST(xDRI2GetFormatsReq);
++    xDRI2GetFormatsReply rep;
++    DrawablePtr pDrawable;
++    unsigned int i, nformats, *formats;
++    int status;
++
++    REQUEST_SIZE_MATCH(xDRI2GetFormatsReq);
++
++    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
++          &status))
++      return status;
++
++    status = DRI2GetFormats(pDrawable->pScreen, &nformats, &formats);
++    if (status != Success)
++      return status;
++
++    rep.type = X_Reply;
++    rep.length = nformats * sizeof(*formats) / 4;
++    rep.sequenceNumber = client->sequence;
++    WriteToClient(client, sizeof(xDRI2GetFormatsReply), &rep);
++
++    for (i = 0; i < nformats; i++) {
++      WriteToClient(client, sizeof(formats[i]), &formats[i]);
++    }
++
++    return Success;
++}
++
++static int
+ ProcDRI2Dispatch (ClientPtr client)
+ {
+     REQUEST(xReq);
+@@ -576,6 +766,16 @@
+       return ProcDRI2WaitSBC(client);
+     case X_DRI2SwapInterval:
+       return ProcDRI2SwapInterval(client);
++    case X_DRI2GetBuffersVid:
++      return ProcDRI2GetBuffersVid(client);
++    case X_DRI2SwapBuffersVid:
++      return ProcDRI2SwapBuffersVid(client);
++    case X_DRI2SetAttribute:
++      return ProcDRI2SetAttribute(client);
++    case X_DRI2GetAttribute:
++      return ProcDRI2GetAttribute(client);
++    case X_DRI2GetFormats:
++      return ProcDRI2GetFormats(client);
+     default:
+       return BadRequest;
+     }
diff --git a/debian/patches/1001-xfree86-modes-Let-the-driver-handle-the-transform.patch b/debian/patches/1001-xfree86-modes-Let-the-driver-handle-the-transform.patch
new file mode 100644 (file)
index 0000000..3f3fb6d
--- /dev/null
@@ -0,0 +1,333 @@
+From 245cb8e94fd15990e1b7d6622added460f104dba Mon Sep 17 00:00:00 2001
+From: Aaron Plattner <aplattner@nvidia.com>
+Date: Thu, 25 Aug 2011 10:19:48 -0700
+Subject: [PATCH 1/2] xfree86/modes: Let the driver handle the transform
+
+If a driver can use hardware to handle the crtc transform, then
+there's no need for the server's shadow layer to do it.  Add a crtc
+flag that lets the driver indicate that it is handling the transform.
+If it's set, consider the transformed size of the screen but don't
+actually enable the shadow layer.  Also stop adjusting the cursor
+image and position.
+
+Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
+---
+ hw/xfree86/modes/xf86Crtc.h    |   16 +++++-
+ hw/xfree86/modes/xf86Cursors.c |   31 +++++++---
+ hw/xfree86/modes/xf86Rotate.c  |  131 +++++++++++++++++++++-------------------
+ 3 files changed, 107 insertions(+), 71 deletions(-)
+
+diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
+index 68a968c..0d7a6a6 100644
+--- a/hw/xfree86/modes/xf86Crtc.h
++++ b/hw/xfree86/modes/xf86Crtc.h
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright © 2006 Keith Packard
++ * Copyright © 2011 Aaron Plattner
+  *
+  * Permission to use, copy, modify, distribute, and sell this software and its
+  * documentation for any purpose is hereby granted without fee, provided that
+@@ -223,7 +224,7 @@ typedef struct _xf86CrtcFuncs {
+ } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
+-#define XF86_CRTC_VERSION 3
++#define XF86_CRTC_VERSION 4
+ struct _xf86Crtc {
+     /**
+@@ -361,6 +362,19 @@ struct _xf86Crtc {
+      * Clear the shadow
+      */
+     Bool          shadowClear;
++
++    /**
++     * Indicates that the driver is handling the transform, so the shadow
++     * surface should be disabled.  The driver writes this field before calling
++     * xf86CrtcRotate to indicate that it is handling the transform (including
++     * rotation and reflection).
++     *
++     * Setting this flag also causes the server to stop adjusting the cursor
++     * image and position.
++     *
++     * Added in ABI version 4
++     */
++    Bool          driverIsPerformingTransform;
+ };
+ typedef struct _xf86OutputFuncs {
+diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
+index 23c48eb..02dea5c 100644
+--- a/hw/xfree86/modes/xf86Cursors.c
++++ b/hw/xfree86/modes/xf86Cursors.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright © 2007 Keith Packard
+- * Copyright © 2010 Aaron Plattner
++ * Copyright © 2010-2011 Aaron Plattner
+  *
+  * Permission to use, copy, modify, distribute, and sell this software and its
+  * documentation for any purpose is hereby granted without fee, provided that
+@@ -47,6 +47,18 @@
+ #include "inputstr.h"
+ /*
++ * Returns the rotation being performed by the server.  If the driver indicates
++ * that it's handling the screen transform, then this returns RR_Rotate_0.
++ */
++static Rotation
++xf86_crtc_cursor_rotation (xf86CrtcPtr crtc)
++{
++    if (crtc->driverIsPerformingTransform)
++      return RR_Rotate_0;
++    return crtc->rotation;
++}
++
++/*
+  * Given a screen coordinate, rotate back to a cursor source coordinate
+  */
+ static void
+@@ -214,6 +226,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
+     int                       xin, yin;
+     int                       flags = cursor_info->Flags;
+     CARD32            bits;
++    const Rotation    rotation = xf86_crtc_cursor_rotation(crtc);
+ #ifdef ARGB_CURSOR
+     crtc->cursor_argb = FALSE;
+@@ -222,7 +235,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
+     for (y = 0; y < cursor_info->MaxHeight; y++)
+       for (x = 0; x < cursor_info->MaxWidth; x++) 
+       {
+-          xf86_crtc_rotate_coord (crtc->rotation,
++          xf86_crtc_rotate_coord (rotation,
+                                   cursor_info->MaxWidth,
+                                   cursor_info->MaxHeight,
+                                   x, y, &xin, &yin);
+@@ -338,7 +351,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+     /*
+      * Transform position of cursor on screen
+      */
+-    if (crtc->transform_in_use)
++    if (crtc->transform_in_use && !crtc->driverIsPerformingTransform)
+     {
+       ScreenPtr       screen = scrn->pScreen;
+       xf86CursorScreenPtr ScreenPriv =
+@@ -420,12 +433,13 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+     CARD8             *cursor_image;
++    const Rotation    rotation = xf86_crtc_cursor_rotation(crtc);
+ #ifdef ARGB_CURSOR
+     crtc->cursor_argb = FALSE;
+ #endif
+-    if (crtc->rotation == RR_Rotate_0)
++    if (rotation == RR_Rotate_0)
+       cursor_image = src;
+     else
+     {
+@@ -439,7 +453,7 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
+         for (y = 0; y < cursor_info->MaxHeight; y++)
+           for (x = 0; x < cursor_info->MaxWidth; x++) 
+           {
+-              xf86_crtc_rotate_coord (crtc->rotation,
++              xf86_crtc_rotate_coord (rotation,
+                                       cursor_info->MaxWidth,
+                                       cursor_info->MaxHeight,
+                                       x, y, &xin, &yin);
+@@ -532,12 +546,13 @@ xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
+     int                       source_height = cursor->bits->height;
+     int                       image_width = cursor_info->MaxWidth;
+     int                       image_height = cursor_info->MaxHeight;
+-    
++    const Rotation    rotation = xf86_crtc_cursor_rotation(crtc);
++
+     for (y = 0; y < image_height; y++)
+       for (x = 0; x < image_width; x++)
+       {
+-          xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
+-                                  x, y, &xin, &yin);
++          xf86_crtc_rotate_coord (rotation, image_width, image_height, x, y,
++                                  &xin, &yin);
+           if (xin < source_width && yin < source_height)
+               bits = cursor_source[yin * source_width + xin];
+           else
+diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
+index 57c3499..45aabf0 100644
+--- a/hw/xfree86/modes/xf86Rotate.c
++++ b/hw/xfree86/modes/xf86Rotate.c
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright © 2006 Keith Packard
++ * Copyright © 2011 Aaron Plattner
+  *
+  * Permission to use, copy, modify, distribute, and sell this software and its
+  * documentation for any purpose is hereby granted without fee, provided that
+@@ -84,7 +85,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
+     int                       n = RegionNumRects(region);
+     BoxPtr            b = RegionRects(region);
+     XID                       include_inferiors = IncludeInferiors;
+-    
++
++    if (crtc->driverIsPerformingTransform)
++      return;
++
+     src = CreatePicture (None,
+                        &root->drawable,
+                        format,
+@@ -290,7 +294,7 @@ xf86RotateDestroy (xf86CrtcPtr crtc)
+     }
+     for (c = 0; c < xf86_config->num_crtc; c++)
+-      if (xf86_config->crtc[c]->transform_in_use)
++      if (xf86_config->crtc[c]->rotatedData)
+           return;
+     /*
+@@ -414,52 +418,73 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
+     }
+     else
+     {
+-      /*
+-       * these are the size of the shadow pixmap, which
+-       * matches the mode, not the pre-rotated copy in the
+-       * frame buffer
+-       */
+-      int         width = crtc->mode.HDisplay;
+-      int         height = crtc->mode.VDisplay;
+-      void        *shadowData = crtc->rotatedData;
+-      PixmapPtr   shadow = crtc->rotatedPixmap;
+-      int         old_width = shadow ? shadow->drawable.width : 0;
+-      int         old_height = shadow ? shadow->drawable.height : 0;
+-
+-      /* Allocate memory for rotation */
+-      if (old_width != width || old_height != height)
+-      {
+-          if (shadow || shadowData)
++      if (crtc->driverIsPerformingTransform) {
++          xf86RotateDestroy(crtc);
++      } else {
++          /*
++           * these are the size of the shadow pixmap, which
++           * matches the mode, not the pre-rotated copy in the
++           * frame buffer
++           */
++          int         width = crtc->mode.HDisplay;
++          int         height = crtc->mode.VDisplay;
++          void        *shadowData = crtc->rotatedData;
++          PixmapPtr   shadow = crtc->rotatedPixmap;
++          int         old_width = shadow ? shadow->drawable.width : 0;
++          int         old_height = shadow ? shadow->drawable.height : 0;
++
++          /* Allocate memory for rotation */
++          if (old_width != width || old_height != height)
+           {
+-              crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+-              crtc->rotatedPixmap = NULL;
+-              crtc->rotatedData = NULL;
++              if (shadow || shadowData)
++              {
++                  crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
++                  crtc->rotatedPixmap = NULL;
++                  crtc->rotatedData = NULL;
++              }
++              shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
++              if (!shadowData)
++                  goto bail1;
++              crtc->rotatedData = shadowData;
++              /* shadow will be damaged in xf86RotatePrepare */
++          }
++          else
++          {
++              /* mark shadowed area as damaged so it will be repainted */
++              damage = TRUE;
+           }
+-          shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
+-          if (!shadowData)
+-              goto bail1;
+-          crtc->rotatedData = shadowData;
+-          /* shadow will be damaged in xf86RotatePrepare */
+-      }
+-      else
+-      {
+-          /* mark shadowed area as damaged so it will be repainted */
+-          damage = TRUE;
+-      }
+-      if (!xf86_config->rotation_damage)
+-      {
+-          /* Create damage structure */
+-          xf86_config->rotation_damage = DamageCreate (NULL, NULL,
+-                                              DamageReportNone,
+-                                              TRUE, pScreen, pScreen);
+           if (!xf86_config->rotation_damage)
+-              goto bail2;
+-          
+-          /* Wrap block handler */
+-          if (!xf86_config->BlockHandler) {
+-              xf86_config->BlockHandler = pScreen->BlockHandler;
+-              pScreen->BlockHandler = xf86RotateBlockHandler;
++          {
++              /* Create damage structure */
++              xf86_config->rotation_damage = DamageCreate (NULL, NULL,
++                                                  DamageReportNone,
++                                                  TRUE, pScreen, pScreen);
++              if (!xf86_config->rotation_damage)
++                  goto bail2;
++
++              /* Wrap block handler */
++              if (!xf86_config->BlockHandler) {
++                  xf86_config->BlockHandler = pScreen->BlockHandler;
++                  pScreen->BlockHandler = xf86RotateBlockHandler;
++              }
++          }
++
++          if (0)
++          {
++      bail2:
++              if (shadow || shadowData)
++              {
++                  crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
++                  crtc->rotatedPixmap = NULL;
++                  crtc->rotatedData = NULL;
++              }
++      bail1:
++              if (old_width && old_height)
++                  crtc->rotatedPixmap =
++                      crtc->funcs->shadow_create (crtc, NULL, old_width,
++                                                  old_height);
++              return FALSE;
+           }
+       }
+ #ifdef RANDR_12_INTERFACE
+@@ -482,24 +507,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
+           }
+       }
+ #endif
+-
+-      if (0)
+-      {
+-    bail2:
+-          if (shadow || shadowData)
+-          {
+-              crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+-              crtc->rotatedPixmap = NULL;
+-              crtc->rotatedData = NULL;
+-          }
+-    bail1:
+-          if (old_width && old_height)
+-              crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+-                                                                NULL,
+-                                                                old_width,
+-                                                                old_height);
+-          return FALSE;
+-      }
+       crtc->transform_in_use = TRUE;
+     }
+     crtc->crtc_to_framebuffer = crtc_to_fb;
+-- 
+1.7.4.1
+
diff --git a/debian/patches/1002-xfree86-modes-Make-cursor-position-transform-a-helpe.patch b/debian/patches/1002-xfree86-modes-Make-cursor-position-transform-a-helpe.patch
new file mode 100644 (file)
index 0000000..bbb3d07
--- /dev/null
@@ -0,0 +1,117 @@
+From 57cd32e93425597317b4b7722859155419836e4c Mon Sep 17 00:00:00 2001
+From: Aaron Plattner <aplattner@nvidia.com>
+Date: Thu, 25 Aug 2011 15:41:55 -0700
+Subject: [PATCH 2/2] xfree86/modes: Make cursor position transform a helper function
+
+When the driver can handle the crtc transform in hardware, it sets
+crtc->driverIsPerformingTransform, which turns off both the shadow
+layer and the cursor's position-transforming code.  However, some
+drivers actually do require the cursor position to still be
+transformed in these cases.  Move the cursor position transform into a
+helper function that can be called by such drivers.
+
+Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
+---
+ hw/xfree86/modes/xf86Crtc.h    |    8 +++++
+ hw/xfree86/modes/xf86Cursors.c |   57 +++++++++++++++++++++------------------
+ 2 files changed, 39 insertions(+), 26 deletions(-)
+
+Index: xserver/hw/xfree86/modes/xf86Crtc.h
+===================================================================
+--- xserver.orig/hw/xfree86/modes/xf86Crtc.h   2012-03-21 16:16:55.085740513 +0100
++++ xserver/hw/xfree86/modes/xf86Crtc.h        2012-03-21 16:16:55.121740513 +0100
+@@ -903,6 +903,14 @@
+ extern _X_EXPORT char *
+ xf86ConnectorGetName(xf86ConnectorType connector);
++/**
++ * Transform the cursor's coordinates based on the crtc transform.  Normally
++ * this is done by the server, but if crtc->driverIsPerformingTransform is TRUE,
++ * then the server does not transform the cursor position automatically.
++ */
++extern _X_EXPORT void
++xf86CrtcTransformCursorPos (xf86CrtcPtr crtc, int *x, int *y);
++
+ /*
+  * Using the desired mode information in each crtc, set
+  * modes (used in EnterVT functions, or at server startup)
+Index: xserver/hw/xfree86/modes/xf86Cursors.c
+===================================================================
+--- xserver.orig/hw/xfree86/modes/xf86Cursors.c        2012-03-21 16:16:55.089740513 +0100
++++ xserver/hw/xfree86/modes/xf86Cursors.c     2012-03-21 16:16:55.121740513 +0100
+@@ -337,7 +337,36 @@
+           xf86_crtc_show_cursor (crtc);
+     }
+ }
+-    
++
++void xf86CrtcTransformCursorPos (xf86CrtcPtr crtc, int *x, int *y)
++{
++    ScrnInfoPtr scrn = crtc->scrn;
++    ScreenPtr screen = scrn->pScreen;
++    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
++    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
++    xf86CursorScreenPtr ScreenPriv =
++      (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
++                                            xf86CursorScreenKey);
++    struct pict_f_vector v;
++    int dx, dy;
++
++    v.v[0] = (*x + ScreenPriv->HotX) + 0.5;
++    v.v[1] = (*y + ScreenPriv->HotY) + 0.5;
++    v.v[2] = 1;
++    pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
++    /* cursor will have 0.5 added to it already so floor is sufficent */
++    *x = floor (v.v[0]);
++    *y = floor (v.v[1]);
++    /*
++     * Transform position of cursor upper left corner
++     */
++    xf86_crtc_rotate_coord_back (crtc->rotation, cursor_info->MaxWidth,
++                               cursor_info->MaxHeight, ScreenPriv->HotX,
++                               ScreenPriv->HotY, &dx, &dy);
++    *x -= dx;
++    *y -= dy;
++}
++
+ static void
+ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+ {
+@@ -346,36 +375,12 @@
+     xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+     DisplayModePtr    mode = &crtc->mode;
+     Bool              in_range;
+-    int                       dx, dy;
+     /*
+      * Transform position of cursor on screen
+      */
+     if (crtc->transform_in_use && !crtc->driverIsPerformingTransform)
+-    {
+-      ScreenPtr       screen = scrn->pScreen;
+-      xf86CursorScreenPtr ScreenPriv =
+-          (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
+-                                                xf86CursorScreenKey);
+-      struct pict_f_vector   v;
+-
+-      v.v[0] = (x + ScreenPriv->HotX) + 0.5;
+-      v.v[1] = (y + ScreenPriv->HotY) + 0.5;
+-      v.v[2] = 1;
+-      pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
+-      /* cursor will have 0.5 added to it already so floor is sufficent */
+-      x = floor (v.v[0]);
+-      y = floor (v.v[1]);
+-      /*
+-       * Transform position of cursor upper left corner
+-       */
+-      xf86_crtc_rotate_coord_back (crtc->rotation,
+-                                   cursor_info->MaxWidth,
+-                                   cursor_info->MaxHeight,
+-                                   ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
+-      x -= dx;
+-      y -= dy;
+-   }
++      xf86CrtcTransformCursorPos(crtc, &x, &y);
+     else
+     {
+       x -= crtc->x;
index e45658c10fb9fa1da99460cd4d126dfdb7fae9ea..ae4891d4b1e1281b5ab7c1c3f95e68a4bd452a25 100644 (file)
@@ -1,5 +1,6 @@
 ## Patches with a number < 100 are applied in debian.
 ## Ubuntu patches start with 100.
+0001-add-dri2video.patch
 001_fedora_extramodes.patch
 02_Add-libnettle-as-option-for-sha1.diff
 07-xfree86-fix-build-with-xv-disabled.diff
@@ -50,3 +51,7 @@
 #514-Xi-drop-forced-unpairing-when-changing-the-hierarchy.patch
 #515-dix-disable-all-devices-before-shutdown.patch
 #516-dix-dont-emulate-scroll-events-for-non-existing-axes.patch
+
+# Rotation patches
+1001-xfree86-modes-Let-the-driver-handle-the-transform.patch
+1002-xfree86-modes-Make-cursor-position-transform-a-helpe.patch