author | Xavier Boudet <x-boudet@ti.com> | |
Tue, 17 Jul 2012 08:21:08 +0000 (10:21 +0200) | ||
committer | Xavier 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/patches/series
debian/changelog | patch | blob | history | |
debian/control | patch | blob | history | |
debian/patches/0001-add-dri2video.patch | [new file with mode: 0644] | patch | blob |
debian/patches/1001-xfree86-modes-Let-the-driver-handle-the-transform.patch | [new file with mode: 0644] | patch | blob |
debian/patches/1002-xfree86-modes-Make-cursor-position-transform-a-helpe.patch | [new file with mode: 0644] | patch | blob |
debian/patches/series | patch | blob | history |
diff --git a/debian/changelog b/debian/changelog
index eefd6271e0230702a3bee2273ee6768665dee968..661760dbd8e44ba4c29eb520c5d2c0f3afaefdab 100644 (file)
--- a/debian/changelog
+++ b/debian/changelog
-- 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:
-- 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:
-- 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
diff --git a/debian/control b/debian/control
index 04363fdaa93f14b076a20007c4a2fe87e89645be..5d714bb156607855fd97f45995ba9dda5bad8583 100644 (file)
--- a/debian/control
+++ b/debian/control
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),
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
--- /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
--- /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
--- /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;
diff --git a/debian/patches/series b/debian/patches/series
index e45658c10fb9fa1da99460cd4d126dfdb7fae9ea..ae4891d4b1e1281b5ab7c1c3f95e68a4bd452a25 100644 (file)
--- a/debian/patches/series
+++ b/debian/patches/series
## 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
#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