Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

383 Commits   1 Branch   1 Tag
Index: Makefile
===================================================================
--- Makefile	(nonexistent)
+++ Makefile	(revision 5)
@@ -0,0 +1,13 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+SOURCE_REQUIRES += ALL_DIRS
+
+
+include ../../../build-system/core.mk
+
+
+download_clean:
+	@true
+
+.PHONY: download_clean
Index: xf86-input-acecad/Makefile
===================================================================
--- xf86-input-acecad/Makefile	(nonexistent)
+++ xf86-input-acecad/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-acecad
+
+versions    = 1.5.0
+pkgname     = xf86-input-acecad
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-acecad
===================================================================
--- xf86-input-acecad	(nonexistent)
+++ xf86-input-acecad	(revision 5)

Property changes on: xf86-input-acecad
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-aiptek/Makefile
===================================================================
--- xf86-input-aiptek/Makefile	(nonexistent)
+++ xf86-input-aiptek/Makefile	(revision 5)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-aiptek
+
+versions    = 1.4.1
+pkgname     = xf86-input-aiptek
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/xf86-input-aiptek-1.4.1-abi.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-1.4.1-abi-patch      ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: xf86-input-aiptek/create-1.4.1-abi-patch/create.patch.sh
===================================================================
--- xf86-input-aiptek/create-1.4.1-abi-patch/create.patch.sh	(nonexistent)
+++ xf86-input-aiptek/create-1.4.1-abi-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=1.4.1
+
+tar --files-from=file.list -xjvf ../xf86-input-aiptek-$VERSION.tar.bz2
+mv xf86-input-aiptek-$VERSION xf86-input-aiptek-$VERSION-orig
+
+cp -rf ./xf86-input-aiptek-$VERSION-new ./xf86-input-aiptek-$VERSION
+
+diff -b --unified -Nr  xf86-input-aiptek-$VERSION-orig  xf86-input-aiptek-$VERSION > xf86-input-aiptek-$VERSION-abi.patch
+
+mv xf86-input-aiptek-$VERSION-abi.patch ../patches
+
+rm -rf ./xf86-input-aiptek-$VERSION
+rm -rf ./xf86-input-aiptek-$VERSION-orig

Property changes on: xf86-input-aiptek/create-1.4.1-abi-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xf86-input-aiptek/create-1.4.1-abi-patch/file.list
===================================================================
--- xf86-input-aiptek/create-1.4.1-abi-patch/file.list	(nonexistent)
+++ xf86-input-aiptek/create-1.4.1-abi-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xf86-input-aiptek-1.4.1/src/xf86Aiptek.c
Index: xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src/xf86Aiptek.c
===================================================================
--- xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src/xf86Aiptek.c	(nonexistent)
+++ xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src/xf86Aiptek.c	(revision 5)
@@ -0,0 +1,2296 @@
+/*
+ * xf86Aiptek
+ *
+ * This driver assumes Linux USB/HID support, available for USB devices.
+ * 
+ * Version 0.0, 1-Jan-2003, Bryan W. Headley
+ *
+ * Version 1.0 10-jan-2008, Rene van Paassen
+ *  * This version is based on the Xorg driver 1.0.1 version, with 
+ *    fixes based on the version developed at aiptektablet.sourceforge.net
+ *    fixes include - correction of the button status calculation
+ *                    (buttons were never released) 
+ *                  - use stylus as default, because reading the
+ *                    tablet before X start gives no hint as to what device
+ *                    it is producing
+ *                  - correction of the proximity bit detection
+ *                  - although tablet may produce relative (x, y), the z and 
+ *                    tilt values are always absolute, corrected that
+ *                  - relative x and y may be negative sometimes! removed 
+ *                    clipping there
+ *                  - filtering out events only if ALL values are equal to 
+ *                    the, previous not when only one or more is equal + 
+ *                    combined filtering with threshold.
+ *                  
+ * 
+ * Copyright 2003 by Bryan W. Headley. <bwheadley@earthlink.net>
+ *
+ * Lineage: This driver is based on both the xf86HyperPen and xf86Wacom tablet
+ *          drivers.
+ *
+ *      xf86HyperPen -- modified from xf86Summa (c) 1996 Steven Lang
+ *          (c) 2000 Roland Jansen
+ *          (c) 2000 Christian Herzog (button & 19200 baud support)
+ *
+ *      xf86Wacom -- (c) 1995-2001 Frederic Lepied
+ *
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Bryan W. Headley not be used in 
+ * advertising or publicity pertaining to distribution of the software 
+ * without specific, written prior permission.  Bryan W. Headley makes no 
+ * representations about the suitability of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+ *
+ * BRYAN W. HEADLEY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL BRYAN W. HEADLEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTIONS, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *
+ * Section "InputDevice"
+ *      Identifier  "stylus"
+ *      Driver      "aiptek"
+ *      Option      "Device"        "pathname" {/dev/input/event0}
+ *      Option      "Type"          "string" {stylus|cursor|eraser}
+ *      Option      "Mode"          "string" {absolute|relative}
+ *      Option      "Cursor"        "string" {stylus|puck}
+ *      Option      "USB"           "bool"   {on|off}
+ *      Option      "ScreenNo"      "int"
+ *      Option      "KeepShape"     "bool"   {on|off}
+ *
+ *      # The tablet reports top-right as 0 for the given coordinate
+ *      # to bottom-left as num (value dependent on tablet.)
+ *      # If you choose to invert X, Y or both, the bottom-left coordinate
+ *      # is reported as 0.
+ *      Option      "InvX"          "bool"   {on|off}
+ *      Option      "InvY"          "bool"   {on|off}
+ *
+ *      # XSize/YSize/XOffset/YOffset allow you to specify an active
+ *      # area within yout tablet.
+ *
+ *      Option      "XSize"         "int"
+ *      Option      "YSize"         "int"
+ *      
+ *      Option      "XTop"          "int"
+ *      Option      "YTop"          "int"
+ *      Option      "XBottom"       "int"
+ *      Option      "YBottom"       "int"
+ *      Option      "XOffset"       "int"
+ *      Option      "YOffset"       "int"
+ *
+ *      Option      "XMax"          "int"
+ *      Option      "YMax"          "int"
+ *      Option      "ZMax"          "int"
+ *      Option      "ZMin"          "int"
+ *
+ *      Option      "XThreshold"  "int"
+ *      Option      "YThreshold"  "int"
+ *      Option      "ZThreshold"  "int"
+ *
+ *      Option      "Pressure"      "Soft|Hard|Linear"  defaults to Linear
+ *
+ *      Option      "alwayscore"  "bool"   {on|off}
+ *      Option      "debuglevel"  "int"
+ *      Option      "HistorySize" "int"
+ * EndSection
+ *
+ *  Commentary:
+ *  1.  Identifier: what you name your input device is not too
+ *      significant. 
+ *      but what it infers is that you can have a driver with
+ *      a name of "stylus" (whose type would be 'stylus') and
+ *      another one with identifier "cursor" (whose type would be
+ *      'cursor') that both would be driver by the same aiptek
+ *      driver. Note though that the identifier keyword has
+ *      no devicetype connotations: you can identify your input
+ *      device as "zzz", 
+ *
+ */
+
+#include "xf86Aiptek.h"
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+
+#include <X11/Xatom.h>
+#include <xserver-properties.h>
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
+#error "Need a server with input ABI 12"
+#endif
+
+static InputDriverPtr aiptekDrv;
+static int debug_level = INI_DEBUG_LEVEL;
+
+static char *default_options[] =
+{
+    "BaudRate",     "9600",
+    "StopBits",     "1",
+    "DataBits",     "8",
+    "Parity",       "None",
+    "VMin",         "1",
+    "Vtime",        "10",
+    "FlowControl",  "Xoff",
+    NULL
+};
+
+_X_EXPORT InputDriverRec AIPTEK =
+{
+    1,                  /* driver version */
+    "aiptek",           /* driver name */
+    NULL,               /* identify */
+    xf86AiptekInit,     /* pre-init */
+    xf86AiptekUninit,   /* un-init */
+    NULL,               /* module */
+    default_options
+};
+
+/*
+ * This is the map of Linux Event Input system keystrokes sent for
+ * the macro keys. There are discrepancies in the mappings, so for example,
+ * if we wanted to implement full macro key-to-string conversion in the
+ * Linux driver, we'd have to accept 1-to-many keyboard events, several of
+ * whom would not have the same encoding. For this reason, we're biting
+ * the bullet now & implementing a simple lookup/translation scheme.
+ * A simple 'KEY_F1 = XK_F1' layout wouldn't work, because X wants an
+ * offset into the KeySym array above, and it'll look up that this means 
+ * XK_whatever...
+ */
+
+static int linux_inputDevice_keyMap[] =
+{
+    KEY_F1,  KEY_F2,  KEY_F3,  KEY_F4,  KEY_F5,  KEY_F6,  KEY_F7,  KEY_F8,
+    KEY_F9,  KEY_F10, KEY_F11, KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16,
+    KEY_F17, KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, KEY_F24, 
+    KEY_STOP, KEY_AGAIN, KEY_PROPS, KEY_UNDO, KEY_FRONT, KEY_COPY,
+    KEY_OPEN, KEY_PASTE
+};
+
+/**********************************************************************
+ * xf86AiptekSendEvents
+ *  Send events according to the device state.
+ */
+static void
+xf86AiptekSendEvents(InputInfoPtr pInfo, int r_z)
+{
+    AiptekDevicePtr device = (AiptekDevicePtr) pInfo->private;
+    AiptekCommonPtr common = device->common;
+
+    int bAbsolute;
+    int x, y, z, xTilt, yTilt;
+
+    if ((DEVICE_ID(device->flags) != common->currentValues.eventType))
+    {
+        DBG(7,"xf86AiptekSendEvents: not the same device type (%u,%u)\n",
+           DEVICE_ID(device->flags), common->currentValues.eventType);
+        return;
+    }
+
+    bAbsolute    = (device->flags & ABSOLUTE_FLAG);
+
+    /*
+     * Normalize X and Y coordinates. This includes dealing
+     * with absolute/relative coordinate mode.
+     */
+    if (bAbsolute)
+    {
+        x = common->currentValues.x;
+        y = common->currentValues.y;
+
+        /* Translate coordinates according to Top and Bottom points.
+         */
+        if (x > device->xBottom) {
+            x = device->xBottom;
+        }
+
+        if (y > device->yBottom) {
+            y = device->yBottom;
+        }
+
+	if (device->xTop > 0) {
+	    DBG(10, "Adjusting x, with xTop=%d\n", device->xTop);
+	    x -= device->xTop;
+	}
+
+	if (device->yTop > 0) {
+	    DBG(10, "Adjusting y, with yTop=%d\n", device->yTop);
+	    y -= device->yTop;
+	}
+
+	if (x < 0) {
+	    x = 0;
+	}
+	if (y < 0) {
+	    y = 0;
+	}
+
+    }
+    else
+    {
+        if (common->previousValues.proximity != 0)
+        {
+            x = common->currentValues.x - common->previousValues.x;
+            y = common->currentValues.y - common->previousValues.y;
+        }
+        else
+        {
+            x = 0;
+            y = 0;
+        }
+    }
+
+    z = r_z;
+    xTilt = common->currentValues.xTilt;
+    yTilt = common->currentValues.yTilt;
+
+    
+    /* Deal with pressure min..max, which differs from threshold. */
+    if (z < device->zMin) {
+        z = 0;
+    }
+
+    if (z > device->zMax) {
+        z = device->zMax;
+    }
+
+    /*
+     * First, handle the macro keys.
+     */
+    if (common->currentValues.macroKey != VALUE_NA)
+    {
+        int i;
+
+        /* This is a little silly, but: The Linux Event Input
+         * system uses a slightly different keymap than does X 
+         * (it also has more keys defined). So, we have to go
+         * through a translation process. It's made sillier than
+         * required because X wants an offset to it's KeySym table,
+         * rather than an event key -- it'll do it's own lookup.
+         * It DOES support arbitrary ordering of key events, and
+         * partial keyboard matrices, so that speaks in favor of this
+         * scheme.
+         */
+        for (i = 0; 
+             i < sizeof(linux_inputDevice_keyMap)/
+                 sizeof(linux_inputDevice_keyMap[0]);
+             ++i)
+        {
+            if (linux_inputDevice_keyMap[i]==common->currentValues.macroKey)
+            {
+                /* First available Keycode begins at 8 => macro+8.
+                 * It's pervasive throughout the Xinput drivers, and
+                 * no, I don't know why they purposively waste the first 8
+                 * positions of the KeySym map...
+                 */
+
+                /* Keyboard 'make' (press) event */
+                xf86PostKeyEvent(pInfo->dev, i+8, TRUE
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 22
+                                 , bAbsolute, 0, 5,
+                                 x, y, common->currentValues.button, xTilt, yTilt
+#endif
+                );
+                /* Keyboard 'break' (depress) event */
+                xf86PostKeyEvent(pInfo->dev, i+8, FALSE
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 22
+                                 , bAbsolute, 0, 5,
+                                 x, y, common->currentValues.button, xTilt, yTilt
+#endif
+                );
+                break;
+            }
+        }
+
+    }
+
+    /* As the coordinates are ready, we can send events to X */
+    if (common->currentValues.proximity)
+    {
+        if (!common->previousValues.proximity)
+                xf86PostProximityEvent(pInfo->dev, 1, 0, 5,
+                    x, y, z, xTilt, yTilt);
+
+        if ((bAbsolute &&
+             (common->previousValues.x != common->currentValues.x ||
+              common->previousValues.y != common->currentValues.y ||
+              common->previousValues.z != common->currentValues.z)) ||
+            (!bAbsolute && 
+             (common->currentValues.x || common->currentValues.y)))
+        {
+            if (bAbsolute || common->previousValues.proximity)
+            {
+                xf86PostMotionEvent(pInfo->dev, bAbsolute, 0, 5,
+                        x, y, z, xTilt, yTilt);
+            }
+        }
+       
+        if (common->previousValues.button != common->currentValues.button)
+        {
+            int delta;
+            delta = common->currentValues.button ^ common->previousValues.button;
+            while(delta)
+            {
+                int id;
+                id = ffs(delta);
+                delta &= ~(1 << (id-1));
+                xf86PostButtonEvent(pInfo->dev, bAbsolute, id,
+                        (common->currentValues.button & (1<<(id-1))), 0, 5,
+                        x, y, z, xTilt, yTilt);
+            }
+        }
+    }
+    else
+    {
+        if (common->previousValues.proximity)
+            xf86PostProximityEvent(pInfo->dev, 0, 0, 5, x, y, z,
+                    xTilt, yTilt);
+        common->previousValues.proximity = 0;
+    }
+}
+
+/*
+ ***************************************************************************
+ * xf86AiptekHIDReadInput --
+ *    Read the new events from the device, and enqueue them.
+ */
+static void
+xf86AiptekHIDReadInput(InputInfoPtr pInfo)
+{
+    AiptekDevicePtr     device = (AiptekDevicePtr) pInfo->private;
+    AiptekCommonPtr     common = device->common;
+
+    ssize_t             len;
+    int                 i;
+    struct input_event* event;
+    char                eventbuf[sizeof(struct input_event) * MAX_EVENTS];
+    int                 eventsInMessage;
+    double              d_z;
+    double              d_zCapacity;
+
+    SYSCALL(len = read(pInfo->fd, eventbuf, sizeof(eventbuf)));
+
+    if (len <= 0)
+    {
+        xf86Msg(X_ERROR, "Error reading Aiptek tablet: %s\n", strerror(errno));
+        return;
+    }
+
+    eventsInMessage = 0;
+    for (event=(struct input_event *)(eventbuf);
+         event<(struct input_event *)(eventbuf+len);
+         ++event)
+    {
+        /*
+         * Unprocessed events:
+         * ABS_RZ - rotate stylus
+         * ABS_DISTANCE - unknown
+         * ABS_THROTTLE - unknown
+         * ABS_WHEEL - we have no wheel
+         * REL_WHEEL - we have no wheel
+         *
+         * Synthesized events
+         * ABS_X_TILT - The aiptek tablet does not report these,
+         * ABS_Y_TILT - but the Linux kernel driver sends synthetic values.
+         */
+        switch (event->type)
+        {
+            case EV_ABS:
+            {
+                switch (event->code)
+                {
+                    case ABS_X:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.x = event->value;
+                    }
+                    break;
+
+                    case ABS_Y:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.y = event->value;
+                    }
+                    break;
+
+                    case ABS_PRESSURE:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.z = event->value;
+                    }
+                    break;
+
+                    case ABS_TILT_X:
+                    case ABS_RZ:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.xTilt = event->value;
+                    }
+                    break;
+
+                    case ABS_TILT_Y:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.yTilt = event->value;
+                    }
+                    break;
+
+                    case ABS_DISTANCE:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.distance = event->value;
+                    }
+                    break;
+
+                    case ABS_WHEEL:
+                    case ABS_THROTTLE:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.wheel = event->value;
+                    }
+                    break;
+
+                    case ABS_MISC:
+                    {
+                        /* We have an agreement with the
+                         * Linux Aiptek HID driver to send
+                         * the proximity bit through ABS_MISC.
+                         * We do this solely if proximity is
+                         * being reported through the Stylus tool;
+                         * else, if mouse, we'll get proximity through
+                         * REL_MISC.
+                         */
+                        ++eventsInMessage;
+                        common->currentValues.proximity = 
+                            PROXIMITY(event->value) ? 1 : 0;
+                    }
+                    break;
+                }
+            }
+            break; /* EV_ABS */
+
+            case EV_REL:
+            {
+                switch (event->code)
+                {
+                    case REL_X:
+                    {
+                        /* Normalize all relative events into absolute
+                         * coordinates.
+                         */
+                        ++eventsInMessage;
+                        common->currentValues.x = 
+                            common->previousValues.x + event->value;
+                    }
+                    break;
+
+                    case REL_Y:
+                    {
+                        /* Normalize all relative events into absolute
+                         * coordinates.
+                         */
+                        ++eventsInMessage;
+                        common->currentValues.y =
+                            common->previousValues.y + event->value;
+                    }
+                    break;
+
+                    case REL_WHEEL:
+                    {
+                        /* Normalize all relative events into absolute
+                         * coordinates.
+                         */
+                        ++eventsInMessage;
+                        common->currentValues.wheel =
+                            common->previousValues.wheel + event->value;
+                    }
+
+                    case REL_MISC:
+                    {
+                        /* We have an agreement with the
+                         * Linux Aiptek HID driver to send
+                         * the proximity bit through REL_MISC.
+                         * We do this solely if proximity is
+                         * being reported through the Mouse tool;
+                         * else, if stylus, we'll get proximity through
+                         * ABS_MISC.
+                         */
+                        ++eventsInMessage;
+                        common->currentValues.proximity = 
+                            PROXIMITY (event->value) ? 1 : 0;
+                    }
+                    break;
+                }
+            }
+            break; /* EV_REL */
+
+            case EV_KEY:
+            {
+                switch (event->code)
+                {
+                    /*
+                     * Events begun with a BTN_TOOL_PEN, PENCIL,
+                     * BRUSH or AIRBRUSH indicate that they are
+                     * destined for the STYLUS device.
+                     *
+                     * This should probably change, and we should
+                     * have devices for each type. We'll address that
+                     * later.
+                     */
+                    case BTN_TOOL_PEN:
+                    case BTN_TOOL_PENCIL:
+                    case BTN_TOOL_BRUSH:
+                    case BTN_TOOL_AIRBRUSH:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.eventType = STYLUS_ID;
+                    }
+                    break;
+
+                    /*
+                     * Events begun with a BTN_TOOL_RUBBER indicate
+                     * that they are destined for the ERASER device.
+                     */
+                    case BTN_TOOL_RUBBER:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.eventType = ERASER_ID;
+                    }
+                    break;
+
+                    /*
+                     * A TOOL_LENS would be for a true PUCK/CURSOR.
+                     * Aiptek instead gives us a mouse, that we can pretend
+                     * is a puck.
+                     */
+                    case BTN_TOOL_MOUSE:
+                    case BTN_TOOL_LENS:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.eventType = CURSOR_ID;
+                    }
+                    break;
+
+                    /*
+                     * Normal button handling: TOUCH, STYLUS and
+                     * STYLUS2 all buttons that we'll report to X
+                     * as normal buttons.
+                     */
+                    case BTN_TOUCH:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_TOUCH;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_TOUCH;
+                    }
+                    break;
+
+                    case BTN_STYLUS:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_STYLUS;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_STYLUS;
+                    }
+                    break;
+
+                    case BTN_STYLUS2:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_STYLUS2;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_STYLUS2;
+                    }
+                    break;
+
+                    /*
+                     * Normal Mouse button handling: LEFT, RIGHT and
+                     * MIDDLE all buttons that we'll report to X
+                     * as normal buttons. Note that the damned things
+                     * re-use the same bitmasks as the Stylus buttons,
+                     * above.
+                     */
+                    case BTN_LEFT:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_MOUSE_LEFT;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_MOUSE_LEFT;
+                    }
+                    break;
+
+                    case BTN_MIDDLE:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_MOUSE_MIDDLE;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_MOUSE_MIDDLE;
+                    }
+                    break;
+
+                    case BTN_RIGHT:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_MOUSE_RIGHT;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_MOUSE_RIGHT;
+                    }
+                    break;
+
+                    case BTN_SIDE:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_SIDE_BTN;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_SIDE_BTN;
+                    }
+                    break;
+
+                    case BTN_EXTRA:
+                    {
+                        ++eventsInMessage;
+                        if (event->value)
+                            common->currentValues.button |= 
+			        BUTTONS_EVENT_EXTRA_BTN;
+			else
+			    common->currentValues.button &= 
+			        ~BUTTONS_EVENT_EXTRA_BTN;
+                    }
+                    break;
+
+                    /*
+                     * Any other EV_KEY event is assumed to be
+                     * the pressing of a macro key from the tablet.
+                     */
+                    default:
+                    {
+                        ++eventsInMessage;
+                        common->currentValues.macroKey = event->code;
+                    }
+                    break;
+                }
+            }
+            break; /* EV_KEY */
+
+        } /* switch event->type */
+
+        /* We have two potential event terminators. EV_MSC was used
+         * by (unwritten) convention to indicate the end-of-report.
+         * Problem is, EV_MSC is supposed to actually report data,
+         * so a new event type, EV_SYN, was created in Linux 2.5.x
+         * expressively for this purpose.
+         *
+         * Theoretically, if EV_SYN is defined, I should only terminate
+         * the population of device->currentValues struct IFF I receive
+         * that event. The fact of the matter is, the EV_MSC is assumed
+         * to be an ugliness that will take some time to be deprecated.
+         * For the nonce, we'll support both. But, if you have a tablet
+         * that's actually supplying something interesting with EV_MSC,
+         * this is obviously some code that requires modifications.
+         */
+#ifndef EV_SYN
+        if (event->type != EV_MSC)
+#else
+        if (event->type != EV_MSC && event->type != EV_SYN)
+#endif
+        {
+            continue;
+        }
+
+        /*
+         * We've seen EV_MSCs in the incoming data trail with no
+         * other message types in-between. We use 'eventsInMessage'
+         * to count all 'real' messages in-between. If there were none,
+         * do NOT copy common->currentValues to common->previousValues
+         * (as this will make the jitter filter useless). Just go and
+         * read the subsequent events.
+         */
+        if (eventsInMessage == 0)
+        {
+            continue;
+        }
+        eventsInMessage = 0;
+
+        /* 
+         * This filter throws out reports that do not meet minimum threshold
+         * requirements for movement along that axis.
+         *
+         * Presently, we discard the entire report if any dimension of the
+         * currentValues struct does not meet it's minimum threshold.
+         *
+         * Also, we only do the comparison IFF a threshold has been set
+         * for that given dimension.
+         */
+        if (ABS(common->currentValues.x - common->previousValues.x)
+                    <= device->xThreshold &&
+            ABS(common->currentValues.y - common->previousValues.y)
+                    <= device->yThreshold &&
+            ABS(common->currentValues.z - common->previousValues.z)
+                    <= device->zThreshold &&
+            ABS(common->currentValues.xTilt - common->previousValues.xTilt)
+                    <= device->xTiltThreshold &&
+            ABS(common->currentValues.yTilt - common->previousValues.yTilt)
+                    <= device->yTiltThreshold &&
+	    common->currentValues.proximity == 
+                    common->previousValues.proximity &&
+            common->currentValues.button ==
+                    common->previousValues.button &&
+            common->currentValues.macroKey ==
+                    common->previousValues.macroKey)
+        {
+            DBG(10, "Event Filtered Out by Thresholds\n");
+            continue;
+        }
+
+        /*
+         * We have three different methods by which we report pressure, Z.
+         * One is to use linear values from 0 to common->zCapacity. The
+         * other two, SOFT_SMOOTH and HARD_SMOOTH, use different
+         * algorithms to 'smooth out' the values.
+         */
+        d_z         = (double)common->currentValues.z;
+        d_zCapacity = (double)common->zCapacity;
+
+        switch (device->zMode)
+        {
+            case VALUE_NA:
+            case PRESSURE_MODE_LINEAR:
+            {
+                /* Leave Z alone. */
+            }
+            break;
+
+            case PRESSURE_MODE_SOFT_SMOOTH:
+            {
+                d_z = (d_z * d_z / d_zCapacity)+ 0.5;
+            }
+            break;
+
+            case PRESSURE_MODE_HARD_SMOOTH:
+            {
+                d_z = (d_zCapacity * sqrt( d_z / d_zCapacity)) + 0.5;
+            }
+            break;
+        }
+
+        /* Dispatch events to all of our configured devices. */
+        for (i=0; i < common->numDevices; ++i)
+        {
+            AiptekDevicePtr dev = common->deviceArray[i]->private;
+            int             id;
+
+            id  = DEVICE_ID (dev->flags);
+
+            /* Find the device the current events are meant for */
+            if (id == common->currentValues.eventType)
+            {
+                /* We left 'z' alone during smoothing, so send up
+                 * perturbed value outside of the struct
+                 */
+                xf86AiptekSendEvents(common->deviceArray[i], (int) d_z);
+            }
+        }
+
+        /*
+         * Copy the values just processed into the previousValues struct,
+         * so we can check for 'jittering' in the subsequent report.
+         */
+        common->previousValues.eventType = common->currentValues.eventType;
+        common->previousValues.x         = common->currentValues.x;
+        common->previousValues.y         = common->currentValues.y;
+        common->previousValues.z         = common->currentValues.z;
+        common->previousValues.proximity = common->currentValues.proximity;
+        common->previousValues.button    = common->currentValues.button;
+        common->previousValues.macroKey  = common->currentValues.macroKey;
+        common->previousValues.xTilt     = common->currentValues.xTilt;
+        common->previousValues.yTilt     = common->currentValues.yTilt;
+        common->previousValues.distance  = common->currentValues.distance;
+        common->previousValues.wheel     = common->currentValues.wheel;
+
+        common->currentValues.macroKey   = VALUE_NA;
+    }
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86AiptekHIDOpen --
+ *
+ ***************************************************************************
+ */
+static Bool
+xf86AiptekHIDOpen(InputInfoPtr pInfo)
+{
+    AiptekDevicePtr device = (AiptekDevicePtr)pInfo->private;
+    AiptekCommonPtr common = device->common;
+    char            name[256] = "Unknown";
+    int             abs[5];
+    unsigned long   bit[EV_MAX][NBITS(KEY_MAX)];
+    int             i, j;
+    int             err = 0;
+    int             version;
+
+    pInfo->fd = xf86OpenSerial(pInfo->options);
+    if (pInfo->fd == -1)
+    {
+        xf86Msg(X_ERROR, "xf86AiptekHIDOpen Error opening %s : %s\n", common->deviceName, strerror(errno));
+        return !Success;
+    }
+
+    ioctl(pInfo->fd, EVIOCGNAME(sizeof(name)), name);
+    xf86Msg(X_PROBED, "HID Device name: \"%s\"\n", name);
+
+    ioctl(pInfo->fd, EVIOCGVERSION, &version);
+    xf86Msg(X_PROBED, "HID Driver Version: %d.%d.%d\n",
+            version>>16, (version>>8) & 0xff, version & 0xff);
+
+    xf86Msg(X_PROBED, "HID Driver knows it has %d devices configured\n",
+            common->numDevices);
+    xf86Msg(X_PROBED, "HID Driver is using %d as the fd\n", pInfo->fd);
+
+    for (i = 0; i < common->numDevices; ++i)
+    {
+        common->deviceArray[i]->read_input = xf86AiptekHIDReadInput;
+        common->deviceArray[i]->fd = pInfo->fd;
+    }
+    common->open = xf86AiptekHIDOpen;
+
+    memset(bit, 0, sizeof(bit));
+    ioctl(pInfo->fd, EVIOCGBIT(0, EV_MAX), bit[0]);
+
+    for (i = 0; i < EV_MAX; ++i)
+    {
+        if (TEST_BIT(i, bit[0]))
+        {
+            ioctl(pInfo->fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
+            for (j = 0; j < KEY_MAX; ++j)
+            {
+                if (TEST_BIT(j, bit[i]))
+                {
+                    if (i == EV_ABS)
+                    {
+                        ioctl(pInfo->fd, EVIOCGABS(j), abs);
+                        switch (j) 
+                        {
+                            case ABS_X:
+                            {
+                                xf86Msg(X_ERROR, "From ioctl() xCapacity=%d\n", abs[2]);
+                                common->xCapacity = abs[2];
+                            }
+                            break;
+
+                            case ABS_Y:
+                            {
+                                xf86Msg(X_ERROR, "From ioctl() yCapacity=%d\n", abs[2]);
+                                common->yCapacity = abs[2];
+                            }
+                            break;
+
+                            case ABS_Z:
+                            {
+                                xf86Msg(X_ERROR, "From ioctl() zCapacity=%d\n", abs[2]);
+                                common->zCapacity = abs[2];
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (err < 0)
+    {
+        xf86Msg(X_ERROR, "xf86AiptekHIDOpen ERROR: %d\n", err);
+        SYSCALL(close(pInfo->fd));
+        return !Success;
+    }
+
+    return Success;
+}
+
+/*
+ * xf86AiptekControlProc
+ */
+static void
+xf86AiptekControlProc(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+    DBG(2, "xf86AiptekControlProc\n");
+}
+
+/*
+** xf86AiptekOpen
+ * Open and initialize the tablet, as well as probe for any needed data.
+ * (This is TTY style open)
+ */
+
+static Bool
+xf86AiptekOpen(InputInfoPtr pInfo)
+{
+    AiptekDevicePtr device = (AiptekDevicePtr)pInfo->private;
+    AiptekCommonPtr common = device->common;
+    int err, version;
+
+    DBG(1, "Opening %s\n", common->deviceName);
+
+    pInfo->fd = xf86OpenSerial(pInfo->options);
+    if (pInfo->fd < 0)
+    {
+        xf86Msg(X_ERROR, "Error opening %s: %s\n", common->deviceName, strerror(errno));
+        return !Success;
+    }
+
+    DBG(1, "Testing USB\n");
+
+    SYSCALL(err = ioctl(pInfo->fd, EVIOCGVERSION, &version));
+    if (!err)
+    {
+        int j;
+
+        SYSCALL(close(pInfo->fd));
+
+        for(j=0; j<common->numDevices; ++j)
+        {
+            common->deviceArray[j]->read_input=xf86AiptekHIDReadInput;
+        }
+        common->open=xf86AiptekHIDOpen;
+
+        return xf86AiptekHIDOpen(pInfo);
+    }
+
+    /* We do not support TTY mode, so just exit angry. */
+    return !Success;
+}
+
+/*
+ * xf86AiptekOpenDevice
+ * Opens and initializes the device driver.
+ */
+static int
+xf86AiptekOpenDevice(DeviceIntPtr pDriver)
+{
+    InputInfoPtr    pInfo  = (InputInfoPtr)pDriver->public.devicePrivate;
+    AiptekDevicePtr   device = pInfo->private;
+    AiptekCommonPtr   common = device->common;
+    double            tabletRatio, screenRatio;
+    double            xFactor, yFactor;
+    int               gap, loop;
+
+    DBG(2, "In xf86AiptekOpenDevice, with fd=%d\n", pInfo->fd);
+
+    if (pInfo->fd < 0)
+    {
+        if (common->initNumber > 2 ||
+            device->initNumber == common->initNumber)
+        {
+            if (common->open(pInfo) != Success)
+            {
+                if (pInfo->fd >= 0)
+                {
+                    SYSCALL(close(pInfo->fd));
+                }
+                pInfo->fd = -1;
+                return !Success;
+            }
+            else
+            {
+                /* Report the file descriptor to all devices */
+                for (loop=0; loop < common->numDevices; ++loop)
+                {
+                    common->deviceArray[loop]->fd = pInfo->fd;
+                }
+            }
+            common->initNumber++;
+        }
+        device->initNumber = common->initNumber;
+    }
+
+    /*
+     * Check our active area parameters. We support the following
+     * three sets of mutually exclusive parameter sets:
+     * 1) xMax/yMax. The origin (0,0) of the active area is the origin
+     *    of the physical tablet. You therefore are describing the
+     *    width and height of that active area.
+     * 2) xOffset/xSize,yOffset/ySize. The origin (0,0) of the active
+     *    area is defined as (xOffset,yOffset) (which we'll report as
+     *    (0,0)). The size of the active area in width and height are
+     *    expressed in coordinates as xSize/ySize. That is to say,
+     *    if xOffset=5; yOffset=5, and xSize=10; ySize=10, then we will 
+     *    have an active area beginning at (5,5) and ending at (15,15).
+     *    Physical coordinate (5,5) is reported as (0,0); (15,15) is 
+     *    reported as (10,10). The rest of the tablet is inert, as far as
+     *    drawing area goes,
+     * 3) xTop/xBottom,yTop/yBottom. The difference between this and
+     *    #2 above is that all four parameters are physical coordinates
+     *    on the tablet. Using the example above, xTop=5; yTop=5, and
+     *    xBottom=15; yBottom=15. It is inferred mathematically that
+     *    the overall active area is 10x10 coordinates.
+     *
+     * NOTE: Mutually exclusive means just that: choose the set of
+     * parameters you like, and use them throughout. If you user xSize,
+     * yOffset and xBottom, we'll have NO idea what you want, and quite
+     * frankly you'll have tempted Fate enough that Bad Things(tm) will
+     * happen to you. Do not complain to us!
+     */
+    if (device->xMax != VALUE_NA ||
+        device->yMax != VALUE_NA)
+    {
+        /* Deal with larger-than-tablet and NA values.
+         */
+        if (device->xMax >  common->xCapacity ||
+            device->xMax == VALUE_NA)
+        {
+            device->xMax = common->xCapacity;
+            xf86Msg(X_CONFIG, "xMax value invalid; adjusting to %d\n",
+                    device->xMax);
+        }
+        if (device->yMax > common->yCapacity ||
+            device->yMax == VALUE_NA)
+        {
+            device->yMax = common->yCapacity;
+            xf86Msg(X_CONFIG,"yMax value invalid; adjusting to %d\n",
+                    device->yMax);
+        }
+
+        /*
+         * Internally we use xTop/yTop/xBottom/yBottom
+         * for everything. It's the easiest for us to work
+         * with, vis-a-vis filtering.
+         */
+
+        device->xTop = 0;
+        device->yTop = 0;
+        device->xBottom = device->xMax;
+        device->yBottom = device->yMax;
+    }
+
+    /*
+     * Deal with xOffset/yOffset;xSize/ySize parameters
+     */
+    if (device->xSize   != VALUE_NA ||
+        device->ySize   != VALUE_NA ||
+        device->xOffset != VALUE_NA ||
+        device->yOffset != VALUE_NA)
+    {
+        int message = 0;
+        /* Simple sanity tests: nothing larger than the
+         * tablet; nothing negative, except for an NA value.
+         */
+        if (device->xOffset  != VALUE_NA &&
+            (device->xOffset >  common->xCapacity ||
+             device->xOffset <  0))
+        {
+            message = 1;
+            device->xOffset = 0;
+        }
+        if (device->yOffset  != VALUE_NA &&
+            (device->yOffset >  common->yCapacity ||
+             device->yOffset <  0))
+        {
+            message = 1;
+            device->yOffset = 0;
+        }
+        if (device->xSize  != VALUE_NA &&
+            (device->xSize >  common->xCapacity ||
+             device->xSize <  0))
+        {
+            message = 1;
+            device->xSize = common->xCapacity;
+        }
+        if (device->ySize  != VALUE_NA &&
+            (device->ySize >  common->yCapacity ||
+             device->ySize <  0))
+        {
+            message = 1;
+            device->ySize = common->yCapacity;
+        }
+
+        /*
+         * If one parameter is set but not the other, we'll
+         * guess at something reasonable for the missing one.
+         */
+        if (device->xOffset == VALUE_NA ||
+            device->xSize   == VALUE_NA)
+        {
+            if (device->xOffset == VALUE_NA)
+            {
+                message = 1;
+                device->xOffset = 0;
+            }
+            else
+            {
+                message = 1;
+                device->xSize = common->xCapacity - device->xOffset;
+            }
+        }
+        if (device->yOffset == VALUE_NA ||
+            device->ySize   == VALUE_NA)
+        {
+            if (device->yOffset == VALUE_NA)
+            {
+                message = 1;
+                device->yOffset = 0;
+            }
+            else
+            {
+                message = 1;
+                device->ySize = common->yCapacity - device->yOffset;
+            }
+        }
+
+        /*
+         * Do not allow the active area to exceed the size of the
+         * tablet. To do this, we have to consider both parameters.
+         * Assumption: xOffset/yOffset is always correct; deliver less
+         * of the tablet than they asked for, if they asked for too much.
+         */
+        if (device->xOffset + device->xSize > common->xCapacity)
+        {
+            message = 1;
+            device->xSize = common->xCapacity - device->xOffset;
+        }
+        if (device->yOffset + device->ySize > common->yCapacity)
+        {
+            message = 1;
+            device->ySize = common->yCapacity - device->yOffset;
+        }
+
+        /*
+         * 'message' is used to indicate that we've changed some parameter
+         * during our filtration process. It's conceivable that we may
+         * have changed parameters several times, so we without commentary
+         * to the very end.
+         */
+        if (message == 1)
+        {
+            xf86Msg(X_CONFIG,"xOffset/yOffset;xSize/ySize values wrong.\n");
+            xf86Msg(X_CONFIG,"xOffset adjusted to %d\n", device->xOffset);
+            xf86Msg(X_CONFIG,"yOffset adjusted to %d\n", device->yOffset);
+            xf86Msg(X_CONFIG,"xSize adjusted to %d\n", device->xSize);
+            xf86Msg(X_CONFIG,"ySize adjusted to %d\n", device->ySize);
+        }
+
+        /*
+         * Internally we use xTop/yTop/xBottom/yBottom
+         * for everything. It's the easiest for us to work
+         * with, vis-a-vis filtering.
+         */
+        device->xTop    = device->xOffset;
+        device->yTop    = device->yOffset;
+        device->xBottom = device->xOffset + device->xSize;
+        device->yBottom = device->yOffset + device->ySize;
+    }
+
+    /*
+     * Third set of parameters. Because everything internally
+     * is expressed as xTop/yTop, etc., I'll do tests on transformed
+     * values from the other parameters as need. My last chance to do
+     * so.
+     */
+    if (device->xTop == VALUE_NA ||
+        device->xTop <  0 ||
+        device->xTop >  common->xCapacity)
+    {
+        device->xTop = 0;
+        xf86Msg(X_CONFIG,"xTop invalid; adjusted to %d\n", device->xTop);
+    }
+    if (device->yTop == VALUE_NA ||
+        device->yTop <  0 ||
+        device->yTop >  common->yCapacity)
+    {
+        device->yTop = 0;
+        xf86Msg(X_CONFIG,"yTop invalid; adjusted to %d\n", device->yTop);
+    }
+    if (device->xBottom == VALUE_NA ||
+        device->xBottom <  0 ||
+        device->xBottom >  common->xCapacity)
+    {
+        device->xBottom = common->xCapacity;
+        xf86Msg(X_CONFIG,"xBottom invalid; adjusted to %d\n", 
+                device->xBottom);
+    }
+    if (device->yBottom == VALUE_NA ||
+        device->yBottom <  0 ||
+        device->yBottom >  common->yCapacity)
+    {
+        device->yBottom = common->yCapacity;
+        xf86Msg(X_CONFIG,"yBottom invalid; adjusted to %d\n", 
+                    device->yBottom);
+    }
+
+    /*
+     * Determine the X screen we're going to be using.
+     * If NA, or larger than the number of screens we
+     * have, or negative, we've going for screen 0, e.g.,
+     * 'default' screen.
+     */
+    if ( device->screenNo >= screenInfo.numScreens ||
+         device->screenNo == VALUE_NA ||
+         device->screenNo < 0) 
+    {
+        device->screenNo = 0;
+        xf86Msg(X_CONFIG,"ScreenNo invalid; adjusted to %d\n", 
+                device->screenNo);
+    }
+
+    /* Calculate the ratio according to KeepShape, TopX and TopY */
+
+    if (device->flags & KEEP_SHAPE_FLAG)
+    {
+        int xDiff, yDiff;
+
+        xDiff = common->xCapacity - device->xTop;
+        yDiff = common->yCapacity - device->yTop;
+
+        tabletRatio = (double) xDiff / (double) yDiff;
+        screenRatio = (double) screenInfo.screens[device->screenNo]->width /
+                      (double) screenInfo.screens[device->screenNo]->height;
+
+        DBG(2, "Screen %d: screenRatio = %.3g, tabletRatio = %.3g\n",
+                  device->screenNo, screenRatio, tabletRatio);
+
+        if (screenRatio > tabletRatio)
+        {
+            gap = (int)((double)common->yCapacity *
+                       (1.0 - tabletRatio/screenRatio));
+            device->xBottom = common->xCapacity;
+            device->yBottom = common->yCapacity - gap;
+            DBG(2, "Screen %d: 'Y' Gap of %d computed\n",
+                  device->screenNo, gap);
+        }
+        else
+        {
+            gap = (int)((double)common->xCapacity *
+                       (1.0 - screenRatio/tabletRatio));
+            device->xBottom = common->xCapacity - gap;
+            device->yBottom = common->yCapacity;
+            DBG(2, "Screen %d: 'X' Gap of %d computed\n",
+                  device->screenNo, gap);
+        }
+    }
+
+    xFactor = (double)screenInfo.screens[device->screenNo]->width/
+        (double)(device->xBottom - device->xTop);
+    yFactor = (double)screenInfo.screens[device->screenNo]->height/
+        (double)(device->yBottom - device->yTop);
+
+    /* 
+     * Check threshold correctness
+     */
+    if (device->xThreshold > common->xCapacity ||
+        device->xThreshold == VALUE_NA ||
+        device->xThreshold <  0)
+    {
+        device->xThreshold = 0;
+    }
+
+    if (device->yThreshold > common->yCapacity ||
+        device->yThreshold == VALUE_NA ||
+        device->yThreshold < 0)
+    {
+        device->yThreshold = 0;
+    }
+
+    if (device->zThreshold > common->zCapacity ||
+        device->zThreshold == VALUE_NA ||
+        device->zThreshold < 0) 
+    {
+        device->zThreshold = 0;
+    }
+
+    /* Create axisStructs for every axis we support.
+     * NOTE: min_resolution and max_resolution infers to
+     * me a programmability to increase/decrease resolution.
+     * We don't support that, so min & max = current_resolution.
+     */
+    InitValuatorAxisStruct(pDriver,                 /* X resolution */
+               0,                                   /* axis_id */
+               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X),
+               0,                                   /* min value */
+               device->xBottom - device->xTop,      /* max value */
+               LPI2CPM(375),                        /* resolution */
+               LPI2CPM(375),                        /* min_resolution */
+               LPI2CPM(375),                        /* max_resolution */
+               Absolute);
+
+    InitValuatorAxisStruct(pDriver,                 /* Y Resolution */
+               1,                                   /* axis_id */
+               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y),
+               0,                                   /* min value */
+               device->yBottom - device->yTop,      /* max value */
+               LPI2CPM(375),                        /* resolution */
+               LPI2CPM(375),                        /* min_resolution */
+               LPI2CPM(375),                        /* max_resolution */
+               Absolute);
+
+    InitValuatorAxisStruct(pDriver,                 /* Pressure */
+               2,                                   /* axis_id */
+               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE),
+               0,                                   /* min value */
+               511,                                 /* max value */
+               512,                                 /* resolution */
+               512,                                 /* min_resolution */
+               512,                                 /* max_resolution */
+               Absolute);
+
+    InitValuatorAxisStruct(pDriver,                 /* xTilt */
+               3,                                   /* axis id */
+               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X),
+               -128,                                /* min value */
+               127,                                 /* max value */
+               256,                                 /* resolution */
+               256,                                 /* min_resolution */
+               256,                                 /* max_resolution */
+               Absolute);
+
+    InitValuatorAxisStruct(pDriver,                 /* yTilt */
+               4,                                   /* axis_id */
+               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y),
+               -128,                                /* min value */
+               127,                                 /* max value */
+               256,                                 /* resolution */
+               256,                                 /* min_resolution */
+               256,                                 /* max_resolution */
+               Absolute);
+
+    /*
+     * The sixth axis would be for wheel support. We do not have
+     * any wheel devices. But if we did, it would be allocated
+     * here.
+     */
+    return (pInfo->fd != -1);
+}
+
+/*
+ * xf86AiptekProc
+ *
+ *  Call dispatcher for this driver.
+ */
+static int
+xf86AiptekProc(DeviceIntPtr pAiptek, int requestCode)
+{
+    CARD8           map[512+1];
+    int             numAxes = 5; /* X, Y, Z, xTilt, yTilt */
+    int             numButtons = 5;
+    int             loop;
+    InputInfoPtr  pInfo  = (InputInfoPtr)pAiptek->public.devicePrivate;
+    AiptekDevicePtr device = pInfo->private;
+    Atom            btn_labels[numAxes];
+    Atom            axes_labels[numButtons];
+
+    DBG(2, "xf86AiptekProc() type=%s flags=%d request=%d\n",
+              (DEVICE_ID(device->flags) == STYLUS_ID) ? "stylus" :
+              (DEVICE_ID(device->flags) == CURSOR_ID) ? "cursor" : "eraser",
+              device->flags, requestCode);
+
+    switch (requestCode)
+    {
+        case DEVICE_INIT:
+        {
+            DBG(1, "xf86AiptekProc request=INIT\n");
+
+            for(loop=1; loop<=numButtons; ++loop)
+            {
+                map[loop] = loop;
+            }
+
+            btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+            btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+            btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+            btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
+            btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+
+            memset(axes_labels, 0, sizeof(axes_labels));
+
+            if (InitButtonClassDeviceStruct(pAiptek,numButtons,
+                                            btn_labels, map) == FALSE)
+            {
+                xf86Msg(X_ERROR, "Unable to init Button Class Device\n");
+                return !Success;
+            }
+
+            if (InitFocusClassDeviceStruct(pAiptek) == FALSE) 
+            {
+                xf86Msg(X_ERROR, "Unable to init Focus Class Device\n");
+                return !Success;
+            }
+
+            if (InitPtrFeedbackClassDeviceStruct(pAiptek,
+                        xf86AiptekControlProc) == FALSE)
+            {
+                xf86Msg(X_ERROR, "Unable to init Pointer Feedback Class Device\n");
+                return !Success;
+            }
+
+            if (InitProximityClassDeviceStruct(pAiptek) == FALSE)
+            {
+                xf86Msg(X_ERROR, "Unable to init Proximity Class Device\n");
+                return !Success;
+            }
+
+            /* we don't label the axes here, done later in
+             * xf86AiptedOpenDevice */
+            if (InitValuatorClassDeviceStruct(pAiptek, numAxes,
+                                              axes_labels, GetMotionHistorySize(),
+                                              ((device->flags & ABSOLUTE_FLAG) ? Absolute : Relative) | OutOfProximity ) == FALSE)
+            {
+                xf86Msg(X_ERROR, "Unable to allocate Valuator Class Device\n");
+                return !Success;
+            }
+
+            /* Allocate the motion history buffer if needed */
+            xf86MotionHistoryAllocate(pInfo);
+
+            /* Open the device to gather information */
+            xf86AiptekOpenDevice(pAiptek);
+        }
+        break;
+
+        case DEVICE_ON:
+        {
+            DBG(1, "xf86AiptekProc request=ON\n");
+
+            if ((pInfo->fd < 0) &&
+                (!xf86AiptekOpenDevice(pAiptek)))
+            {
+                xf86Msg(X_ERROR, "Unable to open aiptek device\n");
+                return !Success;
+            }
+            xf86Msg(X_INFO, "Able to open aiptek device\n");
+            xf86AddEnabledDevice(pInfo);
+            pAiptek->public.on = TRUE;
+        }
+        break;
+
+        case DEVICE_OFF:
+        {
+	    DBG(1, "xf86AiptekProc request=OFF\n");
+            if (pInfo->fd >= 0)
+            {
+                xf86RemoveEnabledDevice(pInfo);
+                xf86AiptekClose(pInfo);
+            }
+            pAiptek->public.on = FALSE;
+        }
+        break;
+
+        case DEVICE_CLOSE:
+        {
+	    DBG(1, "xf86AiptekProc request=CLOSE\n");
+            xf86AiptekClose(pInfo);
+        }
+        break;
+
+        default:
+        {
+            xf86Msg(X_ERROR, "xf86AiptekProc - Unsupported mode=%d\n", requestCode);
+            return !Success;
+        }
+        break;
+    }
+    DBG(2, "xf86AiptekProc Success request=%d\n", requestCode );
+    return Success;
+}
+
+/*
+ * xf86AiptekClose
+ * Perhaps this will close the device
+ */
+static void
+xf86AiptekClose(InputInfoPtr pInfo)
+{
+    if (pInfo->fd >= 0)
+    {
+        SYSCALL(close(pInfo->fd));
+    }
+    pInfo->fd = -1;
+}
+
+/*
+ * xf86AiptekChangeControl
+ * Allow the user to change the tablet resolution -- we have an issue
+ * insofar as we don't know how to write to the tablet. And furthermore,
+ * even if we DID know how to write to the tablet, it doesn't support
+ * a "change resolution" call. We tried to avoid this by claiming when
+ * creating axisStructs that minRes = curRes = maxRes. So, we should never
+ * get dispatched.
+ */
+static int
+xf86AiptekChangeControl(InputInfoPtr pInfo, xDeviceCtl *control)
+{
+    xDeviceResolutionCtl    *res;
+    int                     *resolutions;
+
+    DBG(3, "xf86AiptekChangeControl() entered\n");
+
+    res = (xDeviceResolutionCtl *)control;
+    
+    if ((control->control != DEVICE_RESOLUTION) ||
+        (res->num_valuators < 1))
+    {
+        DBG(3, "xf86AiptekChangeControl abends\n");
+        return (BadMatch);
+    }
+
+    resolutions = (int *)(res +1);
+    
+    DBG(3, "xf86AiptekChangeControl changing to res %d\n",
+              resolutions[0]);
+
+    /* We don't know how to write, yet
+     *
+     * sprintf(str, "SU%d\r", resolutions[0]);
+     * SYSCALL(write(pInfo->fd, str, strlen(str)));
+     */
+
+    return(Success);
+}
+
+/*
+ * xf86AiptekSwitchMode
+ * Switches the mode. For now just absolute or relative, hopefully
+ * more on the way.
+ */
+static int
+xf86AiptekSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
+{
+    InputInfoPtr  pInfo  = (InputInfoPtr)dev->public.devicePrivate;
+    AiptekDevicePtr device = (AiptekDevicePtr)(pInfo->private);
+
+    DBG(3, "xf86AiptekSwitchMode() dev=%p mode=%d\n", dev, mode);
+
+    switch(mode)
+    {
+        case Absolute:
+        {
+            device->flags |= ABSOLUTE_FLAG;
+        }
+        break;
+
+        case Relative:
+        {
+            device->flags &= ~ABSOLUTE_FLAG;
+        }
+        break;
+
+        default:
+        {
+            DBG(1, "xf86AiptekSwitchMode dev=%p invalid mode=%d\n",
+                   dev, mode);
+            return BadMatch;
+        }
+        break;
+    }
+
+    return Success;
+}
+
+/*
+ * xf86AiptekInitialize
+ * Initializes the device structures for the Aiptek.
+ */
+static int
+xf86AiptekAllocate(InputInfoPtr pInfo,
+                   char* name,
+                   int   flag)
+{
+    InputInfoPtr*   deviceArray;
+    AiptekDevicePtr   device;
+    AiptekCommonPtr   common;
+
+    DBG(3, "xf86AiptekAllocate, with %s and %d\n", name, flag);
+
+    device = (AiptekDevicePtr) malloc(sizeof(AiptekDeviceRec));
+    if (!device)
+    {
+        DBG(3, "xf86AiptekAllocate failed to allocate 'device'\n");
+        return BadAlloc;
+    }
+
+    common = (AiptekCommonPtr) malloc(sizeof(AiptekCommonRec));
+    if (!common)
+    {
+        DBG(3, "xf86AiptekAllocate failed to allocate 'common'\n");
+        free(device);
+        return BadAlloc;
+    }
+
+    deviceArray = (InputInfoPtr*) malloc(sizeof(InputInfoPtr));
+    if (!deviceArray)
+    {
+        DBG(3, "xf86AiptekAllocate failed to allocate 'deviceArray'\n");
+        free(device);
+        free(common);
+        return BadAlloc;
+    }
+
+    pInfo->type_name =                  "Aiptek";
+    pInfo->device_control =             xf86AiptekProc;
+    pInfo->read_input =                 xf86AiptekHIDReadInput;
+    pInfo->control_proc =               xf86AiptekChangeControl;
+    pInfo->switch_mode =                xf86AiptekSwitchMode;
+
+    pInfo->fd =             VALUE_NA;
+    pInfo->private =        device;
+
+    device->flags =         flag;       /* various flags (device type, 
+                                         * coordinate type */
+    device->xSize =         VALUE_NA; /* Active Area X */
+    device->ySize =         VALUE_NA; /* Active Area Y */
+    device->xOffset =       VALUE_NA; /* Active area offset X */
+    device->yOffset =       VALUE_NA; /* Active area offset Y */
+    device->xMax =          VALUE_NA; /* Max allowed X value */
+    device->yMax =          VALUE_NA; /* Max allowed Y value */
+    device->zMin =          VALUE_NA; /* Min allowed Z value */
+    device->zMax =          VALUE_NA; /* Max allowed Z value */
+    device->xTop =          VALUE_NA; /* Upper Left X coordinate */
+    device->yTop =          VALUE_NA; /* Upper Left Y coordinate */
+    device->xBottom =       VALUE_NA; /* Lower Right X coordinate */
+    device->yBottom =       VALUE_NA; /* Lower Right Y coordinate */
+    device->xThreshold =    VALUE_NA; /* X delta must be greater than */
+    device->yThreshold =    VALUE_NA; /* Y delta must be greater than */
+    device->zThreshold =    VALUE_NA; /* Z delta must be greater than */
+    device->xTiltThreshold =VALUE_NA;
+    device->yTiltThreshold =VALUE_NA;
+    device->zMode =         VALUE_NA; /* Z: linear, soft, hard log */
+
+    device->initNumber =    VALUE_NA; /* avoid re-init devices */
+    device->screenNo =      VALUE_NA; /* Attached to X screen */
+
+    device->common =        common;   /* Common info pointer */
+
+    /* Record of the event currently being read of the queue */
+    common->currentValues.eventType = STYLUS_ID;   
+                                      /* Device event is for, e.g., */
+                                      /* STYLUS, RUBBER, CURSOR */
+                                      /* Starting with stylus as default */
+    common->currentValues.x         = 0;   /* X coordinate */
+    common->currentValues.y         = 0;   /* Y coordinate */
+    common->currentValues.z         = 0;   /* Z (pressure) */
+    common->currentValues.xTilt     = 0;   /* XTilt */
+    common->currentValues.yTilt     = 0;   /* YTilt */
+    common->currentValues.proximity = 0;   /* proximity bit */
+    common->currentValues.macroKey  = VALUE_NA;   /* tablet macro key code */
+    common->currentValues.button    = 0;   /* bitmask of buttons pressed */
+    common->currentValues.distance  = 0;   /* currently unsupported */
+    common->currentValues.wheel     = 0;   /* likewise */
+
+    /* Record of the event previously read off of the queue */
+    common->previousValues.eventType = 0;  /* Same comments as above */
+    common->previousValues.x         = 0;
+    common->previousValues.y         = 0;
+    common->previousValues.z         = 0;
+    common->previousValues.xTilt     = 0;
+    common->previousValues.yTilt     = 0;
+    common->previousValues.proximity = 0;
+    common->previousValues.macroKey  = VALUE_NA;
+    common->previousValues.button    = 0;
+    common->previousValues.distance  = 0;
+    common->previousValues.wheel     = 0;
+
+    common->deviceName =    "";             /* device file name */
+    common->flags =         0;              /* various flags */
+    common->deviceArray =   deviceArray;    /* Array of tablets */
+    common->deviceArray[0]= pInfo;          /* with pInfo as element */
+    common->numDevices =    1;              /* number of devices */
+
+    common->xCapacity =     0;              /* tablet's max X value */
+    common->yCapacity =     0;              /* tablet's max Y value */
+    common->zCapacity =     0;              /* tablet's max Z value */
+    common->open =          xf86AiptekOpen; /* Open function */
+
+    return Success;
+}
+
+/*
+ * xf86AiptekAllocateStylus
+ */
+static int
+xf86AiptekAllocateStylus(InputInfoPtr pInfo)
+{
+    int rc;
+
+    rc = xf86AiptekAllocate(pInfo, XI_STYLUS, STYLUS_ID);
+    pInfo->type_name = "Stylus";
+
+    return rc;
+}
+
+/*
+ * xf86AiptekAllocateCursor
+ */
+static int
+xf86AiptekAllocateCursor(InputInfoPtr pInfo)
+{
+    int rc;
+
+    rc = xf86AiptekAllocate(pInfo, XI_CURSOR, CURSOR_ID);
+    pInfo->type_name = "Cursor";
+
+    return rc;
+}
+
+/*
+ * xf86AiptekAllocateEraser
+ */
+static int
+xf86AiptekAllocateEraser(InputInfoPtr pInfo)
+{
+    int rc;
+
+    rc = xf86AiptekAllocate(pInfo, XI_ERASER, ABSOLUTE_FLAG|ERASER_ID);
+    pInfo->type_name = "Eraser";
+
+    return rc;
+}
+
+/*
+ * xf86AiptekUninit --
+ *
+ * called when the driver is unloaded.
+ */
+static void
+xf86AiptekUninit(InputDriverPtr    drv,
+                 InputInfoPtr    pInfo,
+                 int               flags)
+{
+    AiptekDevicePtr device = (AiptekDevicePtr) pInfo->private;
+
+    DBG(1, "xf86AiptekUninit\n");
+
+    if (device)
+    {
+        if (device->common)
+        {
+            AiptekCommonPtr common = device->common;
+            int i;
+
+            common->numDevices--;
+
+            for (i = 0; i < common->numDevices; i++)
+            {
+                if (common->deviceArray[i] == pInfo)
+                    memmove(&common->deviceArray[i],
+                            &common->deviceArray[i+1],
+                            (common->numDevices - i) * sizeof(InputInfoPtr));
+            }
+
+            if (common->numDevices == 0)
+                free(common);
+        }
+        device->common = NULL;
+    }
+    pInfo->private = NULL;
+    xf86DeleteInput(pInfo, 0);
+}
+
+/*
+ * xf86AiptekInit --
+ *
+ * Called when the module subsection is found in XF86Config
+ */
+static int
+xf86AiptekInit(InputDriverPtr    drv,
+               InputInfoPtr      pInfo,
+               int               flags)
+{
+    AiptekDevicePtr   device    = NULL;
+    AiptekCommonPtr   common    = NULL;
+    InputInfoPtr    pInfos;
+    char*             s;
+    int               shared;
+    int               rc = BadValue;
+
+    aiptekDrv = drv;
+
+    xf86Msg(X_INFO, "xf86AiptekInit(): begins\n");
+
+/* Type */
+    s = xf86FindOptionValue(pInfo->options, "Type");
+    if (s && (xf86NameCmp(s, "stylus") == 0))
+    {
+        rc = xf86AiptekAllocateStylus(pInfo);
+    }
+    else if (s && (xf86NameCmp(s, "cursor") == 0))
+    {
+        rc = xf86AiptekAllocateCursor(pInfo);
+    }
+    else if (s && (xf86NameCmp(s, "eraser") == 0))
+    {
+        rc = xf86AiptekAllocateEraser(pInfo);
+    }
+    else
+    {
+        xf86Msg(X_ERROR, "%s: No type or invalid type specified.\n"
+                  "Must be one of 'stylus', 'cursor', or 'eraser'\n",
+                  pInfo->name);
+    }
+
+    if(rc != Success)
+        return rc;
+
+    device = (AiptekDevicePtr) pInfo->private;
+
+    common              = device->common;
+
+/* Device */
+/* (mandatory) */
+    common->deviceName = xf86FindOptionValue(pInfo->options, "Device");
+    if(!common->deviceName)
+    {
+        xf86Msg(X_ERROR, "%s: No Device specified.\n", pInfo->name);
+        goto SetupProc_fail;
+    }
+
+    /*
+     * Lookup to see if there is another aiptek device sharing the
+     * same device.
+     */
+
+    shared = 0;
+    for (pInfos = xf86FirstLocalDevice();
+         pInfos != NULL;
+         pInfos = pInfos->next)
+    {
+        if((pInfo != pInfos) &&
+           (pInfos->device_control == xf86AiptekProc) &&
+           (strcmp(((AiptekDevicePtr)pInfos->private)->common->deviceName,
+                    common->deviceName) == 0))
+        {
+            xf86Msg(X_CONFIG,
+                    "xf86AiptekConfig: device shared between %s and %s\n",
+                    pInfo->name,
+                    pInfos->name);
+
+            shared = 1;
+
+            free(common->deviceArray);
+            free(common);
+
+            common = device->common =
+                ((AiptekDevicePtr) pInfos->private)->common;
+            common->numDevices++;
+            common->deviceArray = (InputInfoPtr*)realloc(common->deviceArray,
+                    sizeof(InputInfoPtr)*common->numDevices);
+            common->deviceArray[common->numDevices-1] = pInfo;
+            break;
+        }
+        else
+        {
+            xf86Msg(X_CONFIG, 
+                    "xf86AiptekConfig: device not shared btw %s and %s\n",
+                    pInfo->name, pInfos->name);
+        }
+    }
+
+    /* Process the common options */
+    xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+    /* If this is the first device using the aiptek driver, let's open
+     * the interface so as to obtain legit values for xCapacity and yCapacity
+     * (and then quickly close it). Yes, the word for this is "kludge".
+     * I am sufficiently ashamed :-) TODO kludge alert!
+     */
+    if ( shared == 0)
+    {
+        xf86AiptekHIDOpen(pInfo);
+        close(pInfo->fd);
+        pInfo->fd=-1;
+    }
+
+    /* Optional configuration */
+    xf86Msg(X_CONFIG, "%s device is %s\n", pInfo->name,
+            common->deviceName);
+
+/* DebugLevel */
+    debug_level = xf86SetIntOption(pInfo->options, "DebugLevel", debug_level);
+    if ( debug_level > 0)
+    {
+        xf86Msg(X_CONFIG, "Debug level set to %d\n", debug_level);
+    }
+
+/* zMode */
+    s = xf86FindOptionValue(pInfo->options, "Pressure");
+    if ( s && (xf86NameCmp(s, "hard") == 0))
+    {
+        device->zMode = PRESSURE_MODE_HARD_SMOOTH;
+    }
+    else if ( s && (xf86NameCmp(s, "soft") == 0))
+    {
+        device->zMode = PRESSURE_MODE_SOFT_SMOOTH;
+    }
+    else if (s && (xf86NameCmp(s, "normal") == 0))
+    {
+        device->zMode = PRESSURE_MODE_LINEAR;
+    }
+    else if (s)
+    {
+        xf86Msg(X_ERROR, "%s: invalid Mode ('normal', 'soft' or 'hard').\n",
+            pInfo->name);
+    }
+
+/* Mode */
+    s = xf86FindOptionValue(pInfo->options, "Mode");
+    if (s && (xf86NameCmp(s, "absolute") == 0))
+    {
+        device->flags |= ABSOLUTE_FLAG;
+    }
+    else if (s && (xf86NameCmp(s, "relative") == 0)) 
+    {
+        device->flags &= ~ABSOLUTE_FLAG;
+    }
+    else if (s)
+    {
+        xf86Msg(X_ERROR, "%s: invalid Mode ('absolute' or 'relative').\n",
+            pInfo->name);
+        device->flags |= ABSOLUTE_FLAG;
+    }
+    xf86Msg(X_CONFIG, "%s is in %s mode\n", pInfo->name,
+        (device->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
+
+#ifdef HAVE_LINUX_INPUT_H
+    /* The define-name is accurate; the XFree86 keyword is not. We are
+     * reading from a Linux kernel "Input" device. The Input device
+     * layer generally supports mice, joysticks, and keyboards. As
+     * an extension, the Input device layer also supports HID devices.
+     * HID is a standard specified by the USB Implementors Forum. Ergo,
+     * 99.9% of HID devices are USB devices.
+     *
+     * This option is misnamed, misunderstood, misanthrope. Maybe.
+     */
+    if (xf86SetBoolOption(pInfo->options, "USB",
+                          (common->open == xf86AiptekHIDOpen)))
+    {
+        pInfo->read_input=xf86AiptekHIDReadInput;
+        common->open=xf86AiptekHIDOpen;
+        xf86Msg(X_CONFIG, "%s: reading USB link\n", pInfo->name);
+    }
+#else
+    if (xf86SetBoolOption(pInfo->options, "USB", 0))
+    {
+        xf86Msg(X_ERROR, "The Aiptek USB driver isn't available for your platform.\n");
+        goto SetupProc_fail;
+    }
+#endif
+
+/* ScreenNo */
+    device->screenNo = xf86SetIntOption(pInfo->options, "ScreenNo", VALUE_NA);
+    if (device->screenNo != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: attached to screen number %d\n",
+                pInfo->name, device->screenNo);
+    }
+
+/* KeepShape */
+    if (xf86SetBoolOption(pInfo->options, "KeepShape", 0))
+    {
+        device->flags |= KEEP_SHAPE_FLAG;
+        xf86Msg(X_CONFIG, "%s: keeps shape\n", pInfo->name);
+    }
+
+/* XSize */
+    device->xSize = xf86SetIntOption(pInfo->options, "XSize", device->xSize);
+    device->xSize = xf86SetIntOption(pInfo->options, "SizeX", device->xSize);
+    if (device->xSize != VALUE_NA) 
+    {
+        xf86Msg(X_CONFIG, "%s: XSize/SizeX = %d\n", pInfo->name,
+                device->xSize);
+    }
+
+/* YSize */
+    device->ySize = xf86SetIntOption(pInfo->options, "YSize", device->ySize);
+    device->ySize = xf86SetIntOption(pInfo->options, "SizeY", device->ySize);
+    if (device->ySize != VALUE_NA) 
+    {
+        xf86Msg(X_CONFIG, "%s: YSize/SizeY = %d\n", pInfo->name,
+                device->ySize);
+    }
+
+/* XOffset */
+    device->xOffset = xf86SetIntOption(pInfo->options, "XOffset",
+            device->xOffset);
+    device->xOffset = xf86SetIntOption(pInfo->options, "OffsetX",
+            device->xOffset);
+    if (device->xOffset != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: XOffset/OffsetX = %d\n", pInfo->name,
+                device->xOffset);
+    }
+
+/* YOffset */
+    device->yOffset = xf86SetIntOption(pInfo->options, "YOffset",
+            device->yOffset);
+    device->yOffset = xf86SetIntOption(pInfo->options, "OffsetY",
+            device->yOffset);
+    if (device->yOffset != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: YOffset/OffsetY = %d\n", pInfo->name,
+                device->yOffset);
+    }
+
+/* XThreshold */
+    device->xThreshold = xf86SetIntOption(pInfo->options, "XThreshold",
+            device->xThreshold);
+    device->xThreshold = xf86SetIntOption(pInfo->options, "ThresholdX",
+            device->xThreshold);
+    if (device->xThreshold != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: XThreshold/ThresholdX = %d\n",
+                pInfo->name, device->xThreshold);
+    }
+
+/* YThreshold */
+    device->yThreshold = xf86SetIntOption(pInfo->options, "YThreshold",
+            device->yThreshold);
+    device->yThreshold = xf86SetIntOption(pInfo->options, "ThresholdY",
+            device->yThreshold);
+    if (device->yThreshold != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: YThreshold/ThresholdY = %d\n",
+                pInfo->name, device->yThreshold);
+    }
+
+/* ZThreshold */
+    device->zThreshold = xf86SetIntOption(pInfo->options, "ZThreshold",
+            device->zThreshold);
+    device->zThreshold = xf86SetIntOption(pInfo->options, "ThresholdZ",
+            device->zThreshold);
+    if (device->zThreshold != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: ZThreshold/ThresholdZ = %d\n",
+                pInfo->name, device->zThreshold);
+    }
+
+/* XTiltThreshold */
+    device->xTiltThreshold = xf86SetIntOption(pInfo->options, "XTiltThreshold",
+            device->xTiltThreshold);
+    device->xTiltThreshold = xf86SetIntOption(pInfo->options, "ThresholdXTilt",
+            device->xTiltThreshold);
+    if (device->xTiltThreshold != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: XTiltThreshold = %d\n",
+                pInfo->name, device->xTiltThreshold);
+    }
+
+/* YTiltThreshold */
+    device->yTiltThreshold = xf86SetIntOption(pInfo->options, "YTiltThreshold",
+            device->yTiltThreshold);
+    device->yTiltThreshold = xf86SetIntOption(pInfo->options, "ThresholdYTilt",
+            device->yTiltThreshold);
+    if (device->yTiltThreshold != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: YTiltThreshold = %d\n",
+                pInfo->name, device->yTiltThreshold);
+    }
+
+/* XMax */
+    device->xMax = xf86SetIntOption(pInfo->options, "XMax", device->xMax);
+    device->xMax = xf86SetIntOption(pInfo->options, "MaxX", device->xMax);
+    if (device->xMax != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: XMax/MaxX = %d\n", pInfo->name,
+                device->xMax);
+    }
+
+/* YMax */
+    device->yMax = xf86SetIntOption(pInfo->options, "YMax", device->yMax);
+    device->yMax = xf86SetIntOption(pInfo->options, "MaxY", device->yMax);
+    if (device->yMax != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: YMax/MaxY = %d\n", pInfo->name,
+                device->yMax);
+    }
+
+/* ZMax */
+    device->zMax = xf86SetIntOption(pInfo->options, "ZMax", device->zMax);
+    device->zMax = xf86SetIntOption(pInfo->options, "MaxZ", device->zMax);
+    if (device->zMax != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: ZMax/MaxZ = %d\n", pInfo->name,
+                device->zMax);
+    }
+
+/* ZMin */
+    device->zMin = xf86SetIntOption(pInfo->options, "ZMin", device->zMin);
+    device->zMin = xf86SetIntOption(pInfo->options, "MinZ", device->zMin);
+    if (device->zMin != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: ZMin/MinZ = %d\n", pInfo->name,
+                device->zMin);
+    }
+
+/* TopX */
+    device->xTop = xf86SetIntOption(pInfo->options, "TopX", device->xTop);
+    device->xTop = xf86SetIntOption(pInfo->options, "XTop", device->xTop);
+    if (device->xTop != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: TopX/XTop = %d\n", pInfo->name,
+                device->xTop);
+    }
+
+/* TopY */
+    device->yTop = xf86SetIntOption(pInfo->options, "TopY", device->yTop);
+    device->yTop = xf86SetIntOption(pInfo->options, "YTop", device->yTop);
+    if (device->yTop != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: TopY/YTop = %d\n", pInfo->name,
+                device->yTop);
+    }
+
+/* BottomX */
+    device->xBottom = xf86SetIntOption(pInfo->options, "BottomX",
+            device->xBottom);
+    device->xBottom = xf86SetIntOption(pInfo->options, "XBottom",
+            device->xBottom);
+    if (device->xBottom != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: BottomX/XBottom = %d\n", pInfo->name,
+                device->xBottom);
+    }
+
+/* BottomY */
+    device->yBottom = xf86SetIntOption(pInfo->options, "BottomY",
+            device->yBottom);
+    device->yBottom = xf86SetIntOption(pInfo->options, "YBottom",
+            device->yBottom);
+    if (device->yBottom != VALUE_NA)
+    {
+        xf86Msg(X_CONFIG, "%s: BottomY/YBottom = %d\n", pInfo->name,
+                device->yBottom);
+    }
+
+/* InvX */
+    if (xf86SetBoolOption(pInfo->options, "InvX", FALSE))
+    {
+        device->flags |= INVX_FLAG;
+        xf86Msg(X_CONFIG, "%s: InvX\n", pInfo->name);
+    }
+
+/* InvY */
+    if (xf86SetBoolOption(pInfo->options, "InvY", FALSE))
+    {
+        device->flags |= INVY_FLAG;
+        xf86Msg(X_CONFIG, "%s: InvY\n", pInfo->name);
+    }
+
+/* BaudRate */
+    {
+        int val;
+        val = xf86SetIntOption(pInfo->options, "BaudRate", 0);
+
+        switch(val)
+        {
+            case 19200:
+                break;
+            case 9600:
+                break;
+            default:
+                xf86Msg(X_ERROR, "%s: Illegal BaudRate (9600 or 19200).",
+                        pInfo->name);
+                break;
+        }
+        xf86Msg(X_CONFIG, "%s: BaudRate %u\n", pInfo->name, val);
+    }
+    xf86Msg(X_CONFIG, "%s: xf86AiptekInit() finished\n", pInfo->name);
+
+    return Success;
+
+SetupProc_fail:
+    if (common)
+        free(common);
+    if (device)
+        free(device);
+    if (pInfo)
+        free(pInfo);
+    return BadValue;
+}
+
+/*
+ ***************************************************************************
+ *
+ * Dynamic loading functions
+ *
+ ***************************************************************************
+ */
+/*
+ * xf86AiptekUnplug --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static void
+xf86AiptekUnplug(pointer p)
+{
+    DBG(1, "xf86AiptekUnplug\n");
+}
+
+/*
+ * xf86AiptekPlug --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static pointer
+xf86AiptekPlug(pointer    module,
+               pointer    options,
+               int*       errmaj,
+               int*       errmin)
+{
+    DBG(1, "xf86AiptekPlug\n");
+
+    xf86AddInputDriver(&AIPTEK, module, 0);
+
+    return module;
+}
+
+static XF86ModuleVersionInfo xf86AiptekVersionRec =
+{
+    "aiptek",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+    ABI_CLASS_XINPUT,
+    ABI_XINPUT_VERSION,
+    MOD_CLASS_XINPUT,
+    {0, 0, 0, 0}        /* signature, to be patched into the file by
+                         * a tool
+                         * */
+};
+
+_X_EXPORT XF86ModuleData aiptekModuleData =
+{
+    &xf86AiptekVersionRec,
+    xf86AiptekPlug,
+    xf86AiptekUnplug
+};
+
+/* end of xf86Aiptek.c */
Index: xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src
===================================================================
--- xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src	(nonexistent)
+++ xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src	(revision 5)

Property changes on: xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new/src
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new
===================================================================
--- xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new	(nonexistent)
+++ xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new	(revision 5)

Property changes on: xf86-input-aiptek/create-1.4.1-abi-patch/xf86-input-aiptek-1.4.1-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-aiptek/create-1.4.1-abi-patch
===================================================================
--- xf86-input-aiptek/create-1.4.1-abi-patch	(nonexistent)
+++ xf86-input-aiptek/create-1.4.1-abi-patch	(revision 5)

Property changes on: xf86-input-aiptek/create-1.4.1-abi-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-aiptek/patches/README
===================================================================
--- xf86-input-aiptek/patches/README	(nonexistent)
+++ xf86-input-aiptek/patches/README	(revision 5)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+   TODO: Leave some comment here.
+
+ * end */
Index: xf86-input-aiptek/patches
===================================================================
--- xf86-input-aiptek/patches	(nonexistent)
+++ xf86-input-aiptek/patches	(revision 5)

Property changes on: xf86-input-aiptek/patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-aiptek
===================================================================
--- xf86-input-aiptek	(nonexistent)
+++ xf86-input-aiptek	(revision 5)

Property changes on: xf86-input-aiptek
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-evdev/Makefile
===================================================================
--- xf86-input-evdev/Makefile	(nonexistent)
+++ xf86-input-evdev/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-evdev
+
+versions    = 2.10.6
+pkgname     = xf86-input-evdev
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-evdev
===================================================================
--- xf86-input-evdev	(nonexistent)
+++ xf86-input-evdev	(revision 5)

Property changes on: xf86-input-evdev
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-joystick/Makefile
===================================================================
--- xf86-input-joystick/Makefile	(nonexistent)
+++ xf86-input-joystick/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-joystick
+
+versions    = 1.6.4
+pkgname     = xf86-input-joystick
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-joystick
===================================================================
--- xf86-input-joystick	(nonexistent)
+++ xf86-input-joystick	(revision 5)

Property changes on: xf86-input-joystick
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-keyboard/Makefile
===================================================================
--- xf86-input-keyboard/Makefile	(nonexistent)
+++ xf86-input-keyboard/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-keyboard
+
+versions    = 2.0.0
+pkgname     = xf86-input-keyboard
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-keyboard
===================================================================
--- xf86-input-keyboard	(nonexistent)
+++ xf86-input-keyboard	(revision 5)

Property changes on: xf86-input-keyboard
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-libinput/Makefile
===================================================================
--- xf86-input-libinput/Makefile	(nonexistent)
+++ xf86-input-libinput/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-libinput
+
+versions    = 1.2.1
+pkgname     = xf86-input-libinput
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-libinput
===================================================================
--- xf86-input-libinput	(nonexistent)
+++ xf86-input-libinput	(revision 5)

Property changes on: xf86-input-libinput
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-mouse/Makefile
===================================================================
--- xf86-input-mouse/Makefile	(nonexistent)
+++ xf86-input-mouse/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-mouse
+
+versions    = 1.9.4
+pkgname     = xf86-input-mouse
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-mouse
===================================================================
--- xf86-input-mouse	(nonexistent)
+++ xf86-input-mouse	(revision 5)

Property changes on: xf86-input-mouse
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-penmount/Makefile
===================================================================
--- xf86-input-penmount/Makefile	(nonexistent)
+++ xf86-input-penmount/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-penmount
+
+versions    = 1.5.0
+pkgname     = xf86-input-penmount
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-penmount
===================================================================
--- xf86-input-penmount	(nonexistent)
+++ xf86-input-penmount	(revision 5)

Property changes on: xf86-input-penmount
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-synaptics/Makefile
===================================================================
--- xf86-input-synaptics/Makefile	(nonexistent)
+++ xf86-input-synaptics/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-synaptics
+
+versions    = 1.9.2
+pkgname     = xf86-input-synaptics
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-synaptics
===================================================================
--- xf86-input-synaptics	(nonexistent)
+++ xf86-input-synaptics	(revision 5)

Property changes on: xf86-input-synaptics
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-vmmouse/Makefile
===================================================================
--- xf86-input-vmmouse/Makefile	(nonexistent)
+++ xf86-input-vmmouse/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-vmmouse
+
+versions    = 13.2.0
+pkgname     = xf86-input-vmmouse
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-vmmouse
===================================================================
--- xf86-input-vmmouse	(nonexistent)
+++ xf86-input-vmmouse	(revision 5)

Property changes on: xf86-input-vmmouse
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-void/Makefile
===================================================================
--- xf86-input-void/Makefile	(nonexistent)
+++ xf86-input-void/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-void
+
+versions    = 1.4.2
+pkgname     = xf86-input-void
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-void
===================================================================
--- xf86-input-void	(nonexistent)
+++ xf86-input-void	(revision 5)

Property changes on: xf86-input-void
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-input-wacom/Makefile
===================================================================
--- xf86-input-wacom/Makefile	(nonexistent)
+++ xf86-input-wacom/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-input-wacom
+
+versions    = 1.1.0
+pkgname     = xf86-input-wacom
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-input-wacom
===================================================================
--- xf86-input-wacom	(nonexistent)
+++ xf86-input-wacom	(revision 5)

Property changes on: xf86-input-wacom
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-amdgpu/Makefile
===================================================================
--- xf86-video-amdgpu/Makefile	(nonexistent)
+++ xf86-video-amdgpu/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-amdgpu
+
+versions    = 23.0.0
+pkgname     = xf86-video-amdgpu
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-amdgpu
===================================================================
--- xf86-video-amdgpu	(nonexistent)
+++ xf86-video-amdgpu	(revision 5)

Property changes on: xf86-video-amdgpu
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-apm/Makefile
===================================================================
--- xf86-video-apm/Makefile	(nonexistent)
+++ xf86-video-apm/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-apm
+
+versions    = 1.3.0
+pkgname     = xf86-video-apm
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-apm
===================================================================
--- xf86-video-apm	(nonexistent)
+++ xf86-video-apm	(revision 5)

Property changes on: xf86-video-apm
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-ark/Makefile
===================================================================
--- xf86-video-ark/Makefile	(nonexistent)
+++ xf86-video-ark/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-ark
+
+versions    = 0.7.5
+pkgname     = xf86-video-ark
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-ark
===================================================================
--- xf86-video-ark	(nonexistent)
+++ xf86-video-ark	(revision 5)

Property changes on: xf86-video-ark
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-ast/Makefile
===================================================================
--- xf86-video-ast/Makefile	(nonexistent)
+++ xf86-video-ast/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-ast
+
+versions    = 1.1.6
+pkgname     = xf86-video-ast
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-ast
===================================================================
--- xf86-video-ast	(nonexistent)
+++ xf86-video-ast	(revision 5)

Property changes on: xf86-video-ast
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-ati/Makefile
===================================================================
--- xf86-video-ati/Makefile	(nonexistent)
+++ xf86-video-ati/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-ati
+
+versions    = 19.1.0
+pkgname     = xf86-video-ati
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-ati
===================================================================
--- xf86-video-ati	(nonexistent)
+++ xf86-video-ati	(revision 5)

Property changes on: xf86-video-ati
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-chips/Makefile
===================================================================
--- xf86-video-chips/Makefile	(nonexistent)
+++ xf86-video-chips/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-chips
+
+versions    = 1.4.0
+pkgname     = xf86-video-chips
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-chips
===================================================================
--- xf86-video-chips	(nonexistent)
+++ xf86-video-chips	(revision 5)

Property changes on: xf86-video-chips
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-cirrus/Makefile
===================================================================
--- xf86-video-cirrus/Makefile	(nonexistent)
+++ xf86-video-cirrus/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-cirrus
+
+versions    = 1.6.0
+pkgname     = xf86-video-cirrus
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-cirrus
===================================================================
--- xf86-video-cirrus	(nonexistent)
+++ xf86-video-cirrus	(revision 5)

Property changes on: xf86-video-cirrus
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-dummy/Makefile
===================================================================
--- xf86-video-dummy/Makefile	(nonexistent)
+++ xf86-video-dummy/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-dummy
+
+versions    = 0.4.0
+pkgname     = xf86-video-dummy
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-dummy
===================================================================
--- xf86-video-dummy	(nonexistent)
+++ xf86-video-dummy	(revision 5)

Property changes on: xf86-video-dummy
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-fbdev/Makefile
===================================================================
--- xf86-video-fbdev/Makefile	(nonexistent)
+++ xf86-video-fbdev/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-fbdev
+
+versions    = 0.5.0
+pkgname     = xf86-video-fbdev
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-fbdev
===================================================================
--- xf86-video-fbdev	(nonexistent)
+++ xf86-video-fbdev	(revision 5)

Property changes on: xf86-video-fbdev
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-geode/Makefile
===================================================================
--- xf86-video-geode/Makefile	(nonexistent)
+++ xf86-video-geode/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-geode
+
+versions    = 2.11.20
+pkgname     = xf86-video-geode
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-geode
===================================================================
--- xf86-video-geode	(nonexistent)
+++ xf86-video-geode	(revision 5)

Property changes on: xf86-video-geode
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-glide/Makefile
===================================================================
--- xf86-video-glide/Makefile	(nonexistent)
+++ xf86-video-glide/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-glide
+
+versions    = 1.2.2
+pkgname     = xf86-video-glide
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-glide
===================================================================
--- xf86-video-glide	(nonexistent)
+++ xf86-video-glide	(revision 5)

Property changes on: xf86-video-glide
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-glint/Makefile
===================================================================
--- xf86-video-glint/Makefile	(nonexistent)
+++ xf86-video-glint/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-glint
+
+versions    = 1.2.9
+pkgname     = xf86-video-glint
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-glint
===================================================================
--- xf86-video-glint	(nonexistent)
+++ xf86-video-glint	(revision 5)

Property changes on: xf86-video-glint
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-i128/Makefile
===================================================================
--- xf86-video-i128/Makefile	(nonexistent)
+++ xf86-video-i128/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-i128
+
+versions    = 1.4.0
+pkgname     = xf86-video-i128
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-i128
===================================================================
--- xf86-video-i128	(nonexistent)
+++ xf86-video-i128	(revision 5)

Property changes on: xf86-video-i128
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-i740/Makefile
===================================================================
--- xf86-video-i740/Makefile	(nonexistent)
+++ xf86-video-i740/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-i740
+
+versions    = 1.4.0
+pkgname     = xf86-video-i740
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-i740
===================================================================
--- xf86-video-i740	(nonexistent)
+++ xf86-video-i740	(revision 5)

Property changes on: xf86-video-i740
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-i810/Makefile
===================================================================
--- xf86-video-i810/Makefile	(nonexistent)
+++ xf86-video-i810/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-i810
+
+versions    = 1.7.4
+pkgname     = xf86-video-i810
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-i810
===================================================================
--- xf86-video-i810	(nonexistent)
+++ xf86-video-i810	(revision 5)

Property changes on: xf86-video-i810
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/Makefile
===================================================================
--- xf86-video-intel/Makefile	(nonexistent)
+++ xf86-video-intel/Makefile	(revision 5)
@@ -0,0 +1,60 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-intel
+
+versions    = 2.99.917.2
+pkgname     = xf86-video-intel
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches      = $(CURDIR)/patches/xf86-video-intel-2.99.917.2-die-attributes.patch
+patches     += $(CURDIR)/patches/xf86-video-intel-2.99.917.2-sna-output-attach-edid.patch
+patches     += $(CURDIR)/patches/xf86-video-intel-2.99.917.2-sna-video-definitions.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-2.99.917.2-die-attributes-patch         ; ./create.patch.sh ) ; \
+	 ( cd create-2.99.917.2-sna-output-attach-edid-patch ; ./create.patch.sh ) ; \
+	 ( cd create-2.99.917.2-sna-video-definitions-patch  ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: xf86-video-intel/create-2.99.917.2-die-attributes-patch/create.patch.sh
===================================================================
--- xf86-video-intel/create-2.99.917.2-die-attributes-patch/create.patch.sh	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-die-attributes-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=2.99.917.2
+
+tar --files-from=file.list -xjvf ../xf86-video-intel-$VERSION.tar.bz2
+mv xf86-video-intel-$VERSION xf86-video-intel-$VERSION-orig
+
+cp -rf ./xf86-video-intel-$VERSION-new ./xf86-video-intel-$VERSION
+
+diff --unified -Nr  xf86-video-intel-$VERSION-orig  xf86-video-intel-$VERSION > xf86-video-intel-$VERSION-die-attributes.patch
+
+mv xf86-video-intel-$VERSION-die-attributes.patch ../patches
+
+rm -rf ./xf86-video-intel-$VERSION
+rm -rf ./xf86-video-intel-$VERSION-orig

Property changes on: xf86-video-intel/create-2.99.917.2-die-attributes-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xf86-video-intel/create-2.99.917.2-die-attributes-patch/file.list
===================================================================
--- xf86-video-intel/create-2.99.917.2-die-attributes-patch/file.list	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-die-attributes-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xf86-video-intel-2.99.917.2/test/test.h
Index: xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test/test.h
===================================================================
--- xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test/test.h	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test/test.h	(revision 5)
@@ -0,0 +1,133 @@
+#ifndef TEST_H
+#define TEST_H
+
+#include <stdint.h>
+#include <time.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/Xrender.h>
+
+#define DEFAULT_ITERATIONS 20
+
+enum target {
+	ROOT,
+	CHILD,
+	PIXMAP,
+};
+#define TARGET_FIRST ROOT
+#define TARGET_LAST PIXMAP
+
+enum mask {
+	MASK_NONE,
+	MASK_NONE_AA,
+	MASK_A1,
+	MASK_A8,
+};
+
+struct test {
+	struct test_display {
+		Display *dpy;
+		Window root;
+		XShmSegmentInfo shm;
+		int max_shm_size;
+		int has_shm_pixmaps;
+		int width, height, depth;
+		XRenderPictFormat *format;
+		enum { REF, OUT } target;
+	} out, ref;
+};
+
+void die(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
+
+#define die_unless(expr) do{ if (!(expr)) die("verification failed: %s\n", #expr); } while(0)
+
+void test_init(struct test *test, int argc, char **argv);
+
+void test_compare(struct test *out,
+		  Drawable out_draw, XRenderPictFormat *out_format,
+		  Drawable ref_draw, XRenderPictFormat *ref_format,
+		  int x, int y, int w, int h, const char *info);
+
+#define MAX_DELTA 3
+int pixel_difference(uint32_t a, uint32_t b);
+
+static inline int pixel_equal(int depth, uint32_t a, uint32_t b)
+{
+	if (depth != 32) {
+		uint32_t mask = (1 << depth) - 1;
+		a &= mask;
+		b &= mask;
+	}
+
+	if (a == b)
+		return 1;
+
+	return pixel_difference(a, b) < MAX_DELTA;
+}
+
+void
+test_init_image(XImage *ximage,
+		XShmSegmentInfo *shm,
+		XRenderPictFormat *format,
+		int width, int height);
+
+const char *test_target_name(enum target target);
+
+struct test_target {
+	struct test_display *dpy;
+	Drawable draw;
+	GC gc;
+	XRenderPictFormat *format;
+	Picture picture;
+	int width, height, depth;
+	enum target target;
+};
+
+void test_target_create_render(struct test_display *dpy,
+			       enum target target,
+			       struct test_target *tt);
+void test_target_destroy_render(struct test_display *dpy,
+				struct test_target *tt);
+
+static inline uint32_t depth_mask(int depth)
+{
+	if (depth == 32)
+		return 0xffffffff;
+	else
+		return (1 << depth) - 1;
+}
+
+static inline uint32_t color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
+{
+	uint16_t ra = red * alpha;
+	uint16_t ga = green * alpha;
+	uint16_t ba = blue * alpha;
+
+	return alpha << 24 | ra >> 8 << 16 | ga >> 8 << 8 | ba >> 8;
+}
+
+static inline uint32_t xrender_color(const XRenderColor *c)
+{
+	uint32_t ra = c->red * c->alpha;
+	uint32_t ga = c->green * c->alpha;
+	uint32_t ba = c->blue * c->alpha;
+
+	return c->alpha >> 8 << 24 | ra >> 24 << 16 | ga >> 24 << 8 | ba >> 24;
+}
+
+void test_timer_start(struct test_display *t, struct timespec *tv);
+double test_timer_stop(struct test_display *t, struct timespec *tv);
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+#define SETS(I) ((I) >= 12 ? 1 : 1 << (12 - (I)))
+#define REPS(I) (1 << (I))
+
+#endif
Index: xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test
===================================================================
--- xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new/test
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new
===================================================================
--- xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-die-attributes-patch/xf86-video-intel-2.99.917.2-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-die-attributes-patch
===================================================================
--- xf86-video-intel/create-2.99.917.2-die-attributes-patch	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-die-attributes-patch	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-die-attributes-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/create.patch.sh
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/create.patch.sh	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=2.99.917.2
+
+tar --files-from=file.list -xjvf ../xf86-video-intel-$VERSION.tar.bz2
+mv xf86-video-intel-$VERSION xf86-video-intel-$VERSION-orig
+
+cp -rf ./xf86-video-intel-$VERSION-new ./xf86-video-intel-$VERSION
+
+diff --unified -Nr  xf86-video-intel-$VERSION-orig  xf86-video-intel-$VERSION > xf86-video-intel-$VERSION-sna-output-attach-edid.patch
+
+mv xf86-video-intel-$VERSION-sna-output-attach-edid.patch ../patches
+
+rm -rf ./xf86-video-intel-$VERSION
+rm -rf ./xf86-video-intel-$VERSION-orig

Property changes on: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/file.list
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/file.list	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xf86-video-intel-2.99.917.2/src/sna/sna_display.c
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna/sna_display.c
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna/sna_display.c	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna/sna_display.c	(revision 5)
@@ -0,0 +1,9830 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2013-2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <ctype.h>
+#include <dirent.h>
+
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#elif defined __GNUC__
+#define alloca __builtin_alloca
+#elif defined _AIX
+#define alloca __alloca
+#elif defined _MSC_VER
+#include <malloc.h>
+#define alloca _alloca
+#else
+void *alloca(size_t);
+#endif
+
+#define _PARSE_EDID_
+/* Jump through a few hoops in order to fixup EDIDs */
+#undef VERSION
+#undef REVISION
+
+#include "sna.h"
+#include "sna_reg.h"
+#include "fb/fbpict.h"
+#include "intel_options.h"
+#include "backlight.h"
+
+#include <xf86Crtc.h>
+#include <xf86RandR12.h>
+#include <cursorstr.h>
+
+#if XF86_CRTC_VERSION >= 3
+#define HAS_GAMMA 1
+#else
+#define HAS_GAMMA 0
+#endif
+
+#include <X11/Xatom.h>
+#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H)
+#include <X11/extensions/dpmsconst.h>
+#else
+#define DPMSModeOn 0
+#define DPMSModeOff 3
+#endif
+#include <xf86DDC.h> /* for xf86InterpretEDID */
+
+#include <xf86drm.h>
+
+#ifdef HAVE_VALGRIND
+#include <valgrind.h>
+#include <memcheck.h>
+#endif
+
+#define FAIL_CURSOR_IOCTL 0
+
+/* Minor discrepancy between 32-bit/64-bit ABI in old kernels */
+union compat_mode_get_connector{
+	struct drm_mode_get_connector conn;
+	uint32_t pad[20];
+};
+
+#define KNOWN_MODE_FLAGS ((1<<14)-1)
+
+#ifndef MONITOR_EDID_COMPLETE_RAWDATA
+#define MONITOR_EDID_COMPLETE_RAWDATA 1
+#endif
+
+#ifndef DEFAULT_DPI
+#define DEFAULT_DPI 96
+#endif
+
+#define OUTPUT_STATUS_CACHE_MS 15000
+
+#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
+
+#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
+#define DRM_PLANE_TYPE_OVERLAY 0
+#define DRM_PLANE_TYPE_PRIMARY 1
+#define DRM_PLANE_TYPE_CURSOR  2
+
+#define LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xb9, struct local_mode_obj_get_properties)
+struct local_mode_obj_get_properties {
+	uint64_t props_ptr;
+	uint64_t prop_values_ptr;
+	uint32_t count_props;
+	uint32_t obj_id;
+	uint32_t obj_type;
+	uint32_t pad;
+};
+#define LOCAL_MODE_OBJECT_CRTC 0xcccccccc
+#define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee
+
+struct local_mode_set_plane {
+	uint32_t plane_id;
+	uint32_t crtc_id;
+	uint32_t fb_id; /* fb object contains surface format type */
+	uint32_t flags;
+
+	/* Signed dest location allows it to be partially off screen */
+	int32_t crtc_x, crtc_y;
+	uint32_t crtc_w, crtc_h;
+
+	/* Source values are 16.16 fixed point */
+	uint32_t src_x, src_y;
+	uint32_t src_h, src_w;
+};
+#define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane)
+
+struct local_mode_get_plane {
+	uint32_t plane_id;
+
+	uint32_t crtc_id;
+	uint32_t fb_id;
+
+	uint32_t possible_crtcs;
+	uint32_t gamma_size;
+
+	uint32_t count_format_types;
+	uint64_t format_type_ptr;
+};
+#define LOCAL_IOCTL_MODE_GETPLANE DRM_IOWR(0xb6, struct local_mode_get_plane)
+
+struct local_mode_get_plane_res {
+	uint64_t plane_id_ptr;
+	uint64_t count_planes;
+};
+#define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res)
+
+#if 1
+#define __DBG DBG
+#else
+#define __DBG(x)
+#endif
+
+#define DBG_NATIVE_ROTATION ~0 /* minimum RR_Rotate_0 */
+
+extern XF86ConfigPtr xf86configptr;
+
+struct sna_cursor {
+	struct sna_cursor *next;
+	uint32_t *image;
+	bool transformed;
+	Rotation rotation;
+	int ref;
+	int size;
+	int last_width;
+	int last_height;
+	unsigned handle;
+	unsigned serial;
+	unsigned alloc;
+};
+
+struct sna_crtc {
+	struct sna_crtc_public public;
+	uint32_t id;
+	xf86CrtcPtr base;
+	struct drm_mode_modeinfo kmode;
+	PixmapPtr slave_pixmap;
+	DamagePtr slave_damage;
+	struct kgem_bo *bo, *shadow_bo, *client_bo, *cache_bo;
+	struct sna_cursor *cursor;
+	unsigned int last_cursor_size;
+	uint32_t offset;
+	bool shadow;
+	bool fallback_shadow;
+	bool transform;
+	bool cursor_transform;
+	bool hwcursor;
+	bool flip_pending;
+
+	struct pict_f_transform cursor_to_fb, fb_to_cursor;
+
+	RegionRec crtc_damage;
+	uint16_t shadow_bo_width, shadow_bo_height;
+
+	uint32_t rotation;
+	struct plane {
+		uint32_t id;
+		uint32_t type;
+		struct {
+			uint32_t prop;
+			uint32_t supported;
+			uint32_t current;
+		} rotation;
+		struct {
+			uint32_t prop;
+			uint64_t values[2];
+		} color_encoding;
+		struct list link;
+	} primary;
+	struct list sprites;
+
+	struct drm_color_lut *gamma_lut;
+	uint64_t gamma_lut_prop;
+	uint64_t gamma_lut_blob;
+	uint32_t gamma_lut_size;
+
+	uint32_t mode_serial, flip_serial;
+
+	uint32_t last_seq, wrap_seq;
+	struct ust_msc swap;
+
+	sna_flip_handler_t flip_handler;
+	struct kgem_bo *flip_bo;
+	void *flip_data;
+
+	struct list shadow_link;
+};
+
+struct sna_property {
+	drmModePropertyPtr kprop;
+	int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
+	Atom *atoms;
+};
+
+struct sna_output {
+	xf86OutputPtr base;
+	unsigned id;
+	unsigned serial;
+
+	unsigned possible_encoders;
+	unsigned attached_encoders;
+
+	unsigned int is_panel : 1;
+	unsigned int add_default_modes : 1;
+	int connector_type;
+	int connector_type_id;
+
+	uint32_t link_status_idx;
+
+	uint32_t edid_idx;
+	uint32_t edid_blob_id;
+	uint32_t edid_len;
+	void *edid_raw;
+	void *fake_edid_raw;
+
+	bool has_panel_limits;
+	int panel_hdisplay;
+	int panel_vdisplay;
+
+	uint32_t dpms_id;
+	uint8_t dpms_mode;
+	struct backlight backlight;
+	int backlight_active_level;
+
+	uint32_t last_detect;
+	uint32_t status;
+	unsigned int hotplug_count;
+	bool update_properties;
+	bool reprobe;
+
+	int num_modes;
+	struct drm_mode_modeinfo *modes;
+
+	int num_props;
+	uint32_t *prop_ids;
+	uint64_t *prop_values;
+	struct sna_property *props;
+};
+
+enum { /* XXX copied from hw/xfree86/modes/xf86Crtc.c */
+	OPTION_PREFERRED_MODE,
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,1,0)
+	OPTION_ZOOM_MODES,
+#endif
+	OPTION_POSITION,
+	OPTION_BELOW,
+	OPTION_RIGHT_OF,
+	OPTION_ABOVE,
+	OPTION_LEFT_OF,
+	OPTION_ENABLE,
+	OPTION_DISABLE,
+	OPTION_MIN_CLOCK,
+	OPTION_MAX_CLOCK,
+	OPTION_IGNORE,
+	OPTION_ROTATE,
+	OPTION_PANNING,
+	OPTION_PRIMARY,
+	OPTION_DEFAULT_MODES,
+};
+
+static void __sna_output_dpms(xf86OutputPtr output, int dpms, int fixup);
+static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
+static bool sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc,
+			  struct kgem_bo *bo, int x, int y);
+static void sna_crtc_gamma_set(xf86CrtcPtr crtc,
+			       CARD16 *red, CARD16 *green,
+			       CARD16 *blue, int size);
+
+static bool is_zaphod(ScrnInfoPtr scrn)
+{
+	return xf86IsEntityShared(scrn->entityList[0]);
+}
+
+static bool
+sna_zaphod_match(struct sna *sna, const char *output)
+{
+	const char *s, *colon;
+	char t[20];
+	unsigned int i = 0;
+
+	s = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
+	if (s == NULL)
+		return false;
+
+	colon = strchr(s, ':');
+	if (colon) /* Skip over the ZaphodPipes */
+		s = colon + 1;
+
+	do {
+		/* match any outputs in a comma list, stopping at whitespace */
+		switch (*s) {
+		case '\0':
+			t[i] = '\0';
+			return strcmp(t, output) == 0;
+
+		case ',':
+			t[i] ='\0';
+			if (strcmp(t, output) == 0)
+				return TRUE;
+			i = 0;
+			break;
+
+		case ' ':
+		case '\t':
+		case '\n':
+		case '\r':
+			break;
+
+		default:
+			t[i++] = *s;
+			break;
+		}
+
+		s++;
+	} while (i < sizeof(t));
+
+	return false;
+}
+
+static unsigned
+get_zaphod_crtcs(struct sna *sna)
+{
+	const char *str, *colon;
+	unsigned crtcs = 0;
+
+	str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
+	if (str == NULL || (colon = strchr(str, ':')) == NULL) {
+		DBG(("%s: no zaphod pipes, using screen number: %x\n",
+		     __FUNCTION__,
+		     sna->scrn->confScreen->device->screen));
+		return 1 << sna->scrn->confScreen->device->screen;
+	}
+
+	DBG(("%s: ZaphodHeads='%s'\n", __FUNCTION__, str));
+	while (str < colon) {
+		char *end;
+		unsigned crtc = strtoul(str, &end, 0);
+		if (end == str)
+			break;
+		DBG(("%s: adding CRTC %d to zaphod pipes\n",
+		     __FUNCTION__, crtc));
+		crtcs |= 1 << crtc;
+		str = end + 1;
+	}
+	DBG(("%s: ZaphodPipes=%x\n", __FUNCTION__, crtcs));
+	return crtcs;
+}
+
+inline static unsigned count_to_mask(int x)
+{
+	return (1 << x) - 1;
+}
+
+static inline struct sna_output *to_sna_output(xf86OutputPtr output)
+{
+	return output->driver_private;
+}
+
+static inline int to_connector_id(xf86OutputPtr output)
+{
+	assert(to_sna_output(output));
+	assert(to_sna_output(output)->id);
+	return to_sna_output(output)->id;
+}
+
+static inline struct sna_crtc *to_sna_crtc(xf86CrtcPtr crtc)
+{
+	return crtc->driver_private;
+}
+
+static inline unsigned __sna_crtc_pipe(struct sna_crtc *crtc)
+{
+	return crtc->public.flags >> 8 & 0xff;
+}
+
+static inline unsigned __sna_crtc_id(struct sna_crtc *crtc)
+{
+	return crtc->id;
+}
+
+uint32_t sna_crtc_id(xf86CrtcPtr crtc)
+{
+	return __sna_crtc_id(to_sna_crtc(crtc));
+}
+
+static inline bool event_pending(int fd)
+{
+	struct pollfd pfd;
+	pfd.fd = fd;
+	pfd.events = POLLIN;
+	return poll(&pfd, 1, 0) == 1;
+}
+
+static bool sna_mode_wait_for_event(struct sna *sna)
+{
+	struct pollfd pfd;
+	pfd.fd = sna->kgem.fd;
+	pfd.events = POLLIN;
+	return poll(&pfd, 1, -1) == 1;
+}
+
+static inline uint32_t fb_id(struct kgem_bo *bo)
+{
+	return bo->delta;
+}
+
+unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc)
+{
+	struct plane *sprite;
+	unsigned count;
+
+	count = 0;
+	list_for_each_entry(sprite, &to_sna_crtc(crtc)->sprites, link)
+		count++;
+
+	return count;
+}
+
+static struct plane *lookup_sprite(struct sna_crtc *crtc, unsigned idx)
+{
+	struct plane *sprite;
+
+	list_for_each_entry(sprite, &crtc->sprites, link)
+		if (idx-- == 0)
+			return sprite;
+
+	return NULL;
+}
+
+uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx)
+{
+	struct plane *sprite;
+
+	assert(to_sna_crtc(crtc));
+
+	sprite = lookup_sprite(to_sna_crtc(crtc), idx);
+	return sprite ? sprite->id : 0;
+}
+
+bool sna_crtc_is_transformed(xf86CrtcPtr crtc)
+{
+	assert(to_sna_crtc(crtc));
+	return to_sna_crtc(crtc)->transform;
+}
+
+static inline bool msc64(struct sna_crtc *sna_crtc, uint32_t seq, uint64_t *msc)
+{
+	bool record = true;
+	if (seq < sna_crtc->last_seq) {
+		if (sna_crtc->last_seq - seq > 0x40000000) {
+			sna_crtc->wrap_seq++;
+			DBG(("%s: pipe=%d wrapped; was %u, now %u, wraps=%u\n",
+			     __FUNCTION__, __sna_crtc_pipe(sna_crtc),
+			     sna_crtc->last_seq, seq, sna_crtc->wrap_seq));
+		} else {
+			DBG(("%s: pipe=%d msc went backwards; was %u, now %u; ignoring for last_swap\n",
+			     __FUNCTION__, __sna_crtc_pipe(sna_crtc), sna_crtc->last_seq, seq));
+
+			record = false;
+		}
+	}
+	*msc = (uint64_t)sna_crtc->wrap_seq << 32 | seq;
+	return record;
+}
+
+uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
+			      int tv_sec, int tv_usec, unsigned seq)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	uint64_t msc;
+
+	assert(sna_crtc);
+
+	if (msc64(sna_crtc, seq, &msc)) {
+		DBG(("%s: recording last swap on pipe=%d, frame %d [msc=%08lld], time %d.%06d\n",
+		     __FUNCTION__, __sna_crtc_pipe(sna_crtc), seq, (long long)msc,
+		     tv_sec, tv_usec));
+		sna_crtc->swap.tv_sec = tv_sec;
+		sna_crtc->swap.tv_usec = tv_usec;
+		sna_crtc->swap.msc = msc;
+	} else {
+		DBG(("%s: swap event on pipe=%d, frame %d [msc=%08lld], time %d.%06d\n",
+		     __FUNCTION__, __sna_crtc_pipe(sna_crtc), seq, (long long)msc,
+		     tv_sec, tv_usec));
+	}
+
+	return msc;
+}
+
+const struct ust_msc *sna_crtc_last_swap(xf86CrtcPtr crtc)
+{
+	static struct ust_msc zero;
+
+	if (crtc == NULL) {
+		return &zero;
+	} else {
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		assert(sna_crtc);
+		return &sna_crtc->swap;
+	}
+}
+
+#ifndef NDEBUG
+static void gem_close(int fd, uint32_t handle);
+static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
+			   int width, int height)
+{
+	struct drm_mode_fb_cmd info;
+
+	assert(bo->scanout);
+
+	VG_CLEAR(info);
+	info.fb_id = fb_id(bo);
+
+	assert(drmIoctl(kgem->fd, DRM_IOCTL_MODE_GETFB, &info) == 0);
+	gem_close(kgem->fd, info.handle);
+
+	assert(width <= info.width && height <= info.height);
+}
+#else
+#define assert_scanout(k, b, w, h)
+#endif
+
+static void assert_crtc_fb(struct sna *sna, struct sna_crtc *crtc)
+{
+#ifndef NDEBUG
+	struct drm_mode_crtc mode = { .crtc_id = __sna_crtc_id(crtc) };
+	drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode);
+	assert(mode.fb_id == fb_id(crtc->bo));
+#endif
+}
+
+static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
+		       int width, int height)
+{
+	ScrnInfoPtr scrn = sna->scrn;
+	struct drm_mode_fb_cmd arg;
+
+	if (!kgem_bo_is_fenced(&sna->kgem, bo))
+		return 0;
+
+	assert(bo->refcnt);
+	assert(bo->proxy == NULL);
+	assert(!bo->snoop);
+	assert(8*bo->pitch >= width * scrn->bitsPerPixel);
+	assert(height * bo->pitch <= kgem_bo_size(bo)); /* XXX crtc offset */
+	if (fb_id(bo)) {
+		DBG(("%s: reusing fb=%d for handle=%d\n",
+		     __FUNCTION__, fb_id(bo), bo->handle));
+		assert_scanout(&sna->kgem, bo, width, height);
+		return fb_id(bo);
+	}
+
+	DBG(("%s: create fb %dx%d@%d/%d\n",
+	     __FUNCTION__, width, height, scrn->depth, scrn->bitsPerPixel));
+
+	assert(bo->tiling != I915_TILING_Y || sna->kgem.can_scanout_y);
+	assert((bo->pitch & 63) == 0);
+	assert(scrn->vtSema); /* must be master */
+
+	VG_CLEAR(arg);
+	arg.width = width;
+	arg.height = height;
+	arg.pitch = bo->pitch;
+	arg.bpp = scrn->bitsPerPixel;
+	arg.depth = scrn->depth;
+	arg.handle = bo->handle;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_ADDFB, &arg)) {
+		/* Try again with the fancy version */
+		struct local_mode_fb_cmd2 {
+			uint32_t fb_id;
+			uint32_t width, height;
+			uint32_t pixel_format;
+			uint32_t flags;
+
+			uint32_t handles[4];
+			uint32_t pitches[4]; /* pitch for each plane */
+			uint32_t offsets[4]; /* offset of each plane */
+			uint64_t modifiers[4];
+		} f;
+#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2)
+		memset(&f, 0, sizeof(f));
+		f.width = width;
+		f.height = height;
+		/* XXX interlaced */
+		f.flags = 1 << 1; /* +modifiers */
+		f.handles[0] = bo->handle;
+		f.pitches[0] = bo->pitch;
+
+		switch (bo->tiling) {
+		case I915_TILING_NONE:
+			break;
+		case I915_TILING_X:
+			/* I915_FORMAT_MOD_X_TILED */
+			f.modifiers[0] = (uint64_t)1 << 56 | 1;
+			break;
+		case I915_TILING_Y:
+			/* I915_FORMAT_MOD_X_TILED */
+			f.modifiers[0] = (uint64_t)1 << 56 | 2;
+			break;
+		}
+
+#define fourcc(a,b,c,d) ((a) | (b) << 8 | (c) << 16 | (d) << 24)
+		switch (scrn->depth) {
+		default:
+			ERR(("%s: unhandled screen format, depth=%d\n",
+			     __FUNCTION__, scrn->depth));
+			goto fail;
+		case 8:
+			f.pixel_format = fourcc('C', '8', ' ', ' ');
+			break;
+		case 15:
+			f.pixel_format = fourcc('X', 'R', '1', '5');
+			break;
+		case 16:
+			f.pixel_format = fourcc('R', 'G', '1', '6');
+			break;
+		case 24:
+			f.pixel_format = fourcc('X', 'R', '2', '4');
+			break;
+		case 30:
+			f.pixel_format = fourcc('X', 'R', '3', '0');
+			break;
+		}
+#undef fourcc
+
+		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_ADDFB2, &f)) {
+fail:
+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+				   "%s: failed to add fb: %dx%d depth=%d, bpp=%d, pitch=%d: %d\n",
+				   __FUNCTION__, width, height,
+				   scrn->depth, scrn->bitsPerPixel, bo->pitch, errno);
+			return 0;
+		}
+
+		arg.fb_id = f.fb_id;
+	}
+	assert(arg.fb_id != 0);
+	bo->delta = arg.fb_id;
+	DBG(("%s: attached fb=%d to handle=%d\n",
+	     __FUNCTION__, bo->delta, arg.handle));
+
+	bo->scanout = true;
+	return bo->delta;
+}
+
+static uint32_t gem_create(int fd, int size)
+{
+	struct drm_i915_gem_create create;
+
+	assert((size & 4095) == 0);
+
+	VG_CLEAR(create);
+	create.handle = 0;
+	create.size = size;
+	(void)drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
+
+	return create.handle;
+}
+
+static void *gem_mmap(int fd, int handle, int size)
+{
+	struct drm_i915_gem_mmap_gtt mmap_arg;
+	struct drm_i915_gem_set_domain set_domain;
+	void *ptr;
+
+	VG_CLEAR(mmap_arg);
+	mmap_arg.handle = handle;
+	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg))
+		return NULL;
+
+	ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmap_arg.offset);
+	if (ptr == MAP_FAILED)
+		return NULL;
+
+	VG_CLEAR(set_domain);
+	set_domain.handle = handle;
+	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
+	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
+	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
+		munmap(ptr, size);
+		return NULL;
+	}
+
+	return ptr;
+}
+
+static void gem_close(int fd, uint32_t handle)
+{
+	struct drm_gem_close close;
+
+	VG_CLEAR(close);
+	close.handle = handle;
+	(void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
+}
+
+#define BACKLIGHT_NAME             "Backlight"
+#define BACKLIGHT_DEPRECATED_NAME  "BACKLIGHT"
+static Atom backlight_atom, backlight_deprecated_atom;
+
+#if HAVE_UDEV
+static void
+sna_backlight_uevent(int fd, void *closure)
+{
+	struct sna *sna = closure;
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	DBG(("%s()\n", __FUNCTION__));
+
+	/* Drain the event queue */
+	while (event_pending(fd)) {
+		struct udev_device *dev;
+
+		DBG(("%s: waiting for uevent\n", __FUNCTION__));
+		dev = udev_monitor_receive_device(sna->mode.backlight_monitor);
+		if (dev == NULL)
+			break;
+
+		udev_device_unref(dev);
+	}
+
+	/* Query all backlights for any changes */
+	DBG(("%s: probing backlights for changes\n", __FUNCTION__));
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		struct sna_output *sna_output = to_sna_output(output);
+		int val;
+
+		if (sna_output->dpms_mode != DPMSModeOn)
+			continue;
+
+		val = backlight_get(&sna_output->backlight);
+		if (val < 0)
+			continue;
+		DBG(("%s(%s): backlight '%s' was %d, now %d\n",
+		     __FUNCTION__, output->name, sna_output->backlight.iface,
+		     sna_output->backlight_active_level, val));
+
+		if (val == sna_output->backlight_active_level)
+			continue;
+
+		sna_output->backlight_active_level = val;
+
+		if (output->randr_output) {
+			DBG(("%s(%s): sending change notification\n", __FUNCTION__, output->name));
+			RRChangeOutputProperty(output->randr_output,
+					       backlight_atom, XA_INTEGER,
+					       32, PropModeReplace, 1, &val,
+					       TRUE, FALSE);
+			RRChangeOutputProperty(output->randr_output,
+					       backlight_deprecated_atom, XA_INTEGER,
+					       32, PropModeReplace, 1, &val,
+					       TRUE, FALSE);
+		}
+	}
+	DBG(("%s: complete\n", __FUNCTION__));
+}
+
+static void sna_backlight_pre_init(struct sna *sna)
+{
+	struct udev *u;
+	struct udev_monitor *mon;
+
+#if !USE_BACKLIGHT
+	return;
+#endif
+
+	u = udev_new();
+	if (!u)
+		return;
+
+	mon = udev_monitor_new_from_netlink(u, "udev");
+	if (!mon)
+		goto free_udev;
+
+	if (udev_monitor_filter_add_match_subsystem_devtype(mon, "backlight", NULL))
+		goto free_monitor;
+
+	if (udev_monitor_enable_receiving(mon))
+		goto free_monitor;
+
+	sna->mode.backlight_handler =
+		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
+				      sna_backlight_uevent, sna);
+	if (!sna->mode.backlight_handler)
+		goto free_monitor;
+
+	DBG(("%s: installed backlight monitor\n", __FUNCTION__));
+	sna->mode.backlight_monitor = mon;
+
+	return;
+
+free_monitor:
+	udev_monitor_unref(mon);
+free_udev:
+	udev_unref(u);
+}
+
+static void sna_backlight_drain_uevents(struct sna *sna)
+{
+	if (sna->mode.backlight_monitor == NULL)
+		return;
+
+	DBG(("%s()\n", __FUNCTION__));
+	sna_backlight_uevent(udev_monitor_get_fd(sna->mode.backlight_monitor),
+			     sna);
+}
+
+static void sna_backlight_close(struct sna *sna)
+{
+	struct udev *u;
+
+	if (sna->mode.backlight_handler == NULL)
+		return;
+
+	xf86RemoveGeneralHandler(sna->mode.backlight_handler);
+
+	u = udev_monitor_get_udev(sna->mode.backlight_monitor);
+	udev_monitor_unref(sna->mode.backlight_monitor);
+	udev_unref(u);
+
+	sna->mode.backlight_handler = NULL;
+	sna->mode.backlight_monitor = NULL;
+}
+#else
+static void sna_backlight_pre_init(struct sna *sna) { }
+static void sna_backlight_drain_uevents(struct sna *sna) { }
+static void sna_backlight_close(struct sna *sna) { }
+#endif
+
+static void
+sna_output_backlight_disable(struct sna_output *sna_output)
+{
+	xf86OutputPtr output = sna_output->base;
+
+	xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+		   "Failed to set backlight %s for output %s, disabling\n",
+		   sna_output->backlight.iface, output->name);
+	backlight_disable(&sna_output->backlight);
+	if (output->randr_output) {
+		RRDeleteOutputProperty(output->randr_output, backlight_atom);
+		RRDeleteOutputProperty(output->randr_output, backlight_deprecated_atom);
+	}
+}
+
+static int
+sna_output_backlight_set(struct sna_output *sna_output, int level)
+{
+	int ret = 0;
+
+	DBG(("%s(%s) level=%d, max=%d\n", __FUNCTION__,
+	     sna_output->base->name, level, sna_output->backlight.max));
+
+	if (backlight_set(&sna_output->backlight, level)) {
+		sna_output_backlight_disable(sna_output);
+		ret = -1;
+	}
+
+	/* Consume the uevent notification now so that we don't misconstrue
+	 * the change latter when we wake up and the output is in a different
+	 * state.
+	 */
+	sna_backlight_drain_uevents(to_sna(sna_output->base->scrn));
+	return ret;
+}
+
+static bool
+has_native_backlight(struct sna_output *sna_output)
+{
+	return sna_output->backlight.type == BL_RAW;
+}
+
+static void
+sna_output_backlight_off(struct sna_output *sna_output)
+{
+	/* Trust the kernel to turn the native backlight off. However, we
+	 * do explicitly turn the backlight back on (when we wake the output)
+	 * just in case a third party turns it off!
+	 */
+	if (has_native_backlight(sna_output))
+		return;
+
+	DBG(("%s(%s)\n", __FUNCTION__, sna_output->base->name));
+	backlight_off(&sna_output->backlight);
+	sna_output_backlight_set(sna_output, 0);
+}
+
+static void
+sna_output_backlight_on(struct sna_output *sna_output)
+{
+	DBG(("%s(%s)\n", __FUNCTION__, sna_output->base->name));
+	sna_output_backlight_set(sna_output,
+				 sna_output->backlight_active_level);
+	if (backlight_on(&sna_output->backlight) < 0)
+		sna_output_backlight_disable(sna_output);
+}
+
+static int
+sna_output_backlight_get(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	int level = backlight_get(&sna_output->backlight);
+	DBG(("%s(%s) level=%d, max=%d\n", __FUNCTION__,
+	     output->name, level, sna_output->backlight.max));
+	return level;
+}
+
+static char *
+has_user_backlight_override(xf86OutputPtr output)
+{
+	struct sna *sna = to_sna(output->scrn);
+	const char *str;
+
+	str = xf86GetOptValString(sna->Options, OPTION_BACKLIGHT);
+	if (str == NULL)
+		return NULL;
+
+	DBG(("%s(%s) requested %s\n", __FUNCTION__, output->name, str));
+	if (*str == '\0')
+		return (char *)str;
+
+	if (!backlight_exists(str)) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			   "Unrecognised backlight control interface '%s'\n",
+			   str);
+		return NULL;
+	}
+
+	return strdup(str);
+}
+
+static int get_device_minor(int fd)
+{
+	struct stat st;
+
+	if (fstat(fd, &st) || !S_ISCHR(st.st_mode))
+		return -1;
+
+	return st.st_rdev & 0x63;
+}
+
+static const char * const sysfs_connector_types[] = {
+	/* DRM_MODE_CONNECTOR_Unknown */	"Unknown",
+	/* DRM_MODE_CONNECTOR_VGA */		"VGA",
+	/* DRM_MODE_CONNECTOR_DVII */		"DVI-I",
+	/* DRM_MODE_CONNECTOR_DVID */		"DVI-D",
+	/* DRM_MODE_CONNECTOR_DVIA */		"DVI-A",
+	/* DRM_MODE_CONNECTOR_Composite */	"Composite",
+	/* DRM_MODE_CONNECTOR_SVIDEO */		"SVIDEO",
+	/* DRM_MODE_CONNECTOR_LVDS */		"LVDS",
+	/* DRM_MODE_CONNECTOR_Component */	"Component",
+	/* DRM_MODE_CONNECTOR_9PinDIN */	"DIN",
+	/* DRM_MODE_CONNECTOR_DisplayPort */	"DP",
+	/* DRM_MODE_CONNECTOR_HDMIA */		"HDMI-A",
+	/* DRM_MODE_CONNECTOR_HDMIB */		"HDMI-B",
+	/* DRM_MODE_CONNECTOR_TV */		"TV",
+	/* DRM_MODE_CONNECTOR_eDP */		"eDP",
+	/* DRM_MODE_CONNECTOR_VIRTUAL */	"Virtual",
+	/* DRM_MODE_CONNECTOR_DSI */		"DSI",
+	/* DRM_MODE_CONNECTOR_DPI */		"DPI"
+};
+
+static char *has_connector_backlight(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	struct sna *sna = to_sna(output->scrn);
+	char path[1024];
+	DIR *dir;
+	struct dirent *de;
+	int minor, len;
+	char *str = NULL;
+
+	if (sna_output->connector_type >= ARRAY_SIZE(sysfs_connector_types))
+		return NULL;
+
+	minor = get_device_minor(sna->kgem.fd);
+	if (minor < 0)
+		return NULL;
+
+	len = snprintf(path, sizeof(path),
+		       "/sys/class/drm/card%d-%s-%d",
+		       minor,
+		       sysfs_connector_types[sna_output->connector_type],
+		       sna_output->connector_type_id);
+	DBG(("%s: lookup %s\n", __FUNCTION__, path));
+
+	dir = opendir(path);
+	if (dir == NULL)
+		return NULL;
+
+	while ((de = readdir(dir))) {
+		struct stat st;
+
+		if (*de->d_name == '.')
+			continue;
+
+		snprintf(path + len, sizeof(path) - len,
+			 "/%s", de->d_name);
+
+		if (stat(path, &st))
+			continue;
+
+		if (!S_ISDIR(st.st_mode))
+			continue;
+
+		DBG(("%s: testing %s as backlight\n",
+		     __FUNCTION__, de->d_name));
+
+		if (backlight_exists(de->d_name)) {
+			str = strdup(de->d_name); /* leak! */
+			break;
+		}
+	}
+
+	closedir(dir);
+	return str;
+}
+
+static void
+sna_output_backlight_init(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	struct pci_device *pci;
+	MessageType from;
+	char *best_iface;
+
+#if !USE_BACKLIGHT
+	return;
+#endif
+
+	if (sna_output->is_panel) {
+		from = X_CONFIG;
+		best_iface = has_user_backlight_override(output);
+		if (best_iface)
+			goto done;
+	}
+
+	best_iface = has_connector_backlight(output);
+	if (best_iface)
+		goto done;
+
+	if (!sna_output->is_panel)
+		return;
+
+	/* XXX detect right backlight for multi-GPU/panels */
+	from = X_PROBED;
+	pci = xf86GetPciInfoForEntity(to_sna(output->scrn)->pEnt->index);
+	if (pci != NULL)
+		best_iface = backlight_find_for_device(pci);
+
+done:
+	DBG(("%s(%s) opening backlight %s\n", __FUNCTION__,
+	     output->name, best_iface ?: "none"));
+	sna_output->backlight_active_level =
+		backlight_open(&sna_output->backlight, best_iface);
+	DBG(("%s(%s): initial backlight value %d\n",
+	     __FUNCTION__, output->name, sna_output->backlight_active_level));
+	if (sna_output->backlight_active_level < 0)
+		return;
+
+	switch (sna_output->backlight.type) {
+	case BL_FIRMWARE: best_iface = (char *)"firmware"; break;
+	case BL_PLATFORM: best_iface = (char *)"platform"; break;
+	case BL_RAW: best_iface = (char *)"raw"; break;
+	default: best_iface = (char *)"unknown"; break;
+	}
+	xf86DrvMsg(output->scrn->scrnIndex, from,
+		   "Found backlight control interface %s (type '%s') for output %s\n",
+		   sna_output->backlight.iface, best_iface, output->name);
+}
+
+#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(22, 0)
+static inline int sigio_block(void)
+{
+	return 0;
+}
+static inline void sigio_unblock(int was_blocked)
+{
+	(void)was_blocked;
+}
+#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
+static inline int sigio_block(void)
+{
+	OsBlockSIGIO();
+	return 0;
+}
+static inline void sigio_unblock(int was_blocked)
+{
+	OsReleaseSIGIO();
+	(void)was_blocked;
+}
+#else
+#include <xf86_OSproc.h>
+static inline int sigio_block(void)
+{
+	return xf86BlockSIGIO();
+}
+static inline void sigio_unblock(int was_blocked)
+{
+	xf86UnblockSIGIO(was_blocked);
+}
+#endif
+
+static char *canonical_kmode_name(const struct drm_mode_modeinfo *kmode)
+{
+	char tmp[32], *buf;
+	int len;
+
+	len = sprintf(tmp, "%dx%d%s",
+		      kmode->hdisplay, kmode->vdisplay,
+		      kmode->flags & V_INTERLACE ? "i" : "");
+	if ((unsigned)len >= sizeof(tmp))
+		return NULL;
+
+	buf = malloc(len + 1);
+	if (buf == NULL)
+		return NULL;
+
+	return memcpy(buf, tmp, len + 1);
+}
+
+static char *get_kmode_name(const struct drm_mode_modeinfo *kmode)
+{
+	if (*kmode->name == '\0')
+		return canonical_kmode_name(kmode);
+
+	return strdup(kmode->name);
+}
+
+static DisplayModePtr
+mode_from_kmode(ScrnInfoPtr scrn,
+		const struct drm_mode_modeinfo *kmode,
+		DisplayModePtr mode)
+{
+	DBG(("kmode: %s, clock=%d, %d %d %d %d %d, %d %d %d %d %d, flags=%x, type=%x\n",
+	     kmode->name, kmode->clock,
+	     kmode->hdisplay, kmode->hsync_start, kmode->hsync_end, kmode->htotal, kmode->hskew,
+	     kmode->vdisplay, kmode->vsync_start, kmode->vsync_end, kmode->vtotal, kmode->vscan,
+	     kmode->flags, kmode->type));
+
+	mode->status = MODE_OK;
+
+	mode->Clock = kmode->clock;
+
+	mode->HDisplay = kmode->hdisplay;
+	mode->HSyncStart = kmode->hsync_start;
+	mode->HSyncEnd = kmode->hsync_end;
+	mode->HTotal = kmode->htotal;
+	mode->HSkew = kmode->hskew;
+
+	mode->VDisplay = kmode->vdisplay;
+	mode->VSyncStart = kmode->vsync_start;
+	mode->VSyncEnd = kmode->vsync_end;
+	mode->VTotal = kmode->vtotal;
+	mode->VScan = kmode->vscan;
+
+	mode->VRefresh = kmode->vrefresh;
+	mode->Flags = kmode->flags;
+	mode->name = get_kmode_name(kmode);
+
+	if (kmode->type & DRM_MODE_TYPE_DRIVER)
+		mode->type = M_T_DRIVER;
+	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+		mode->type |= M_T_PREFERRED;
+
+	if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS)
+		mode->status = MODE_BAD; /* unknown flags => unhandled */
+
+	xf86SetModeCrtc(mode, scrn->adjustFlags);
+	return mode;
+}
+
+static void
+mode_to_kmode(struct drm_mode_modeinfo *kmode, DisplayModePtr mode)
+{
+	memset(kmode, 0, sizeof(*kmode));
+
+	kmode->clock = mode->Clock;
+	kmode->hdisplay = mode->HDisplay;
+	kmode->hsync_start = mode->HSyncStart;
+	kmode->hsync_end = mode->HSyncEnd;
+	kmode->htotal = mode->HTotal;
+	kmode->hskew = mode->HSkew;
+
+	kmode->vdisplay = mode->VDisplay;
+	kmode->vsync_start = mode->VSyncStart;
+	kmode->vsync_end = mode->VSyncEnd;
+	kmode->vtotal = mode->VTotal;
+	kmode->vscan = mode->VScan;
+
+	kmode->vrefresh = mode->VRefresh;
+	kmode->flags = mode->Flags;
+	if (mode->name)
+		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
+	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+}
+
+static void
+sna_crtc_force_outputs_on(xf86CrtcPtr crtc)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	/* All attached outputs are valid, so update our timestamps */
+	unsigned now = GetTimeInMillis();
+	int i;
+
+	assert(to_sna_crtc(crtc));
+	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc)));
+
+	/* DPMS handling by the kernel is inconsistent, so after setting a
+	 * mode on an output presume that we intend for it to be on, or that
+	 * the kernel will force it on.
+	 *
+	 * So force DPMS to be on for all connected outputs, and restore
+	 * the backlight.
+	 */
+	for (i = 0; i < config->num_output; i++) {
+		xf86OutputPtr output = config->output[i];
+
+		if (output->crtc != crtc)
+			continue;
+
+		__sna_output_dpms(output, DPMSModeOn, false);
+		if (to_sna_output(output)->last_detect)
+			to_sna_output(output)->last_detect = now;
+	}
+
+#if XF86_CRTC_VERSION >= 3
+	crtc->active = TRUE;
+#endif
+}
+
+static void
+sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	int i;
+
+	assert(to_sna_crtc(crtc));
+	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc)));
+
+	/* DPMS handling by the kernel is inconsistent, so after setting a
+	 * mode on an output presume that we intend for it to be on, or that
+	 * the kernel will force it on.
+	 *
+	 * So force DPMS to be on for all connected outputs, and restore
+	 * the backlight.
+	 */
+	for (i = 0; i < config->num_output; i++) {
+		xf86OutputPtr output = config->output[i];
+
+		if (output->crtc != crtc)
+			continue;
+
+		__sna_output_dpms(output, DPMSModeOff, false);
+	}
+}
+
+static unsigned
+rotation_reflect(unsigned rotation)
+{
+	unsigned other_bits;
+
+	/* paranoia for future extensions */
+	other_bits = rotation & ~RR_Rotate_All;
+
+	/* flip the reflection to compensate for reflecting the rotation */
+	other_bits ^= RR_Reflect_X | RR_Reflect_Y;
+
+	/* Reflect the screen by rotating the rotation bit,
+	 * which has to have at least RR_Rotate_0 set. This allows
+	 * us to reflect any of the rotation bits, not just 0.
+	 */
+	rotation &= RR_Rotate_All;
+	assert(rotation);
+	rotation <<= 2; /* RR_Rotate_0 -> RR_Rotate_180 etc */
+	rotation |= rotation >> 4; /* RR_Rotate_270' to RR_Rotate_90 */
+	rotation &= RR_Rotate_All;
+	assert(rotation);
+
+	return rotation | other_bits;
+}
+
+static unsigned
+rotation_reduce(struct plane *p, unsigned rotation)
+{
+	/* If unsupported try exchanging rotation for a reflection */
+	if (rotation & ~p->rotation.supported) {
+		unsigned new_rotation = rotation_reflect(rotation);
+		if ((new_rotation & p->rotation.supported) == new_rotation)
+			rotation = new_rotation;
+	}
+
+	/* Only one rotation bit should be set */
+	assert(is_power_of_two(rotation & RR_Rotate_All));
+
+	return rotation;
+}
+
+static bool
+rotation_set(struct sna *sna, struct plane *p, uint32_t desired)
+{
+#define LOCAL_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xbA, struct local_mode_obj_set_property)
+	struct local_mode_obj_set_property {
+		uint64_t value;
+		uint32_t prop_id;
+		uint32_t obj_id;
+		uint32_t obj_type;
+		uint32_t pad;
+	} prop;
+
+	if (desired == p->rotation.current)
+		return true;
+
+	if ((desired & p->rotation.supported) != desired) {
+		errno = EINVAL;
+		return false;
+	}
+
+	DBG(("%s: obj=%d, type=%x prop=%d set-rotation=%x\n",
+	     __FUNCTION__, p->id, LOCAL_MODE_OBJECT_PLANE, p->rotation.prop, desired));
+
+	assert(p->id);
+	assert(p->rotation.prop);
+
+	VG_CLEAR(prop);
+	prop.obj_id = p->id;
+	prop.obj_type = LOCAL_MODE_OBJECT_PLANE;
+	prop.prop_id = p->rotation.prop;
+	prop.value = desired;
+
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_SETPROPERTY, &prop))
+		return false;
+
+	p->rotation.current = desired;
+	return true;
+}
+
+static void
+rotation_reset(struct plane *p)
+{
+	if (p->rotation.prop == 0)
+		return;
+
+	p->rotation.current = 0;
+}
+
+bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc,
+				  unsigned idx,
+				  uint32_t rotation)
+{
+	struct plane *sprite;
+	assert(to_sna_crtc(crtc));
+
+	sprite = lookup_sprite(to_sna_crtc(crtc), idx);
+	if (!sprite)
+		return false;
+
+	DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n",
+	     __FUNCTION__,
+	     sna_crtc_id(crtc), sna_crtc_pipe(crtc),
+	     sprite->id, rotation));
+
+	return rotation_set(to_sna(crtc->scrn), sprite,
+			    rotation_reduce(sprite, rotation));
+}
+
+#if HAS_DEBUG_FULL
+#if !HAS_DEBUG_FULL
+#define LogF ErrorF
+#endif
+struct kmsg {
+	int fd;
+	int saved_loglevel;
+};
+
+static int kmsg_get_debug(void)
+{
+	int v = -1;
+	int fd;
+
+	fd = open("/sys/module/drm/parameters/debug", O_RDONLY);
+	if (fd != -1) {
+		char buf[128];
+		int len;
+
+		len = read(fd, buf, sizeof(buf) - 1);
+		if (len != -1) {
+			buf[len] = '\0';
+			v = atoi(buf);
+		}
+		close(fd);
+	}
+
+	return v;
+}
+
+static void kmsg_set_debug(int v)
+{
+	char buf[128];
+	int len;
+	int fd;
+
+	len = snprintf(buf, sizeof(buf), "%d\n", v);
+
+	fd = open("/sys/module/drm/parameters/debug", O_WRONLY);
+	if (fd != -1) {
+		write(fd, buf, len);
+		close(fd);
+	}
+}
+
+static void kmsg_open(struct kmsg *k)
+{
+	k->saved_loglevel = kmsg_get_debug();
+	if (k->saved_loglevel != -1)
+		kmsg_set_debug(0xff);
+
+	k->fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
+	if (k->fd != -1)
+		lseek(k->fd, 0, SEEK_END);
+}
+
+static void kmsg_close(struct kmsg *k, int dump)
+{
+	FILE *file;
+
+	file = NULL;
+	if (k->fd != -1 && dump)
+		file = fdopen(k->fd, "r");
+	if (file) {
+		size_t len = 0;
+		char *line = NULL;
+
+		while (getline(&line, &len, file) != -1) {
+			char *start = strchr(line, ';');
+			if (start)
+				LogF("KMSG: %s", start + 1);
+		}
+
+		free(line);
+		fclose(file);
+	}
+
+	if (k->fd != -1)
+		close(k->fd);
+
+	if (k->saved_loglevel != -1)
+		kmsg_set_debug(k->saved_loglevel);
+}
+#else
+struct kmsg { int unused; };
+static void kmsg_open(struct kmsg *k) {}
+static void kmsg_close(struct kmsg *k, int dump) {}
+#endif
+
+static int
+sna_crtc_apply(xf86CrtcPtr crtc)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	struct drm_mode_crtc arg;
+	uint32_t output_ids[32];
+	int output_count = 0;
+	int sigio, i;
+	struct kmsg kmsg;
+	int ret = EINVAL;
+
+	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__,
+	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
+	     sna_crtc->bo->handle));
+	if (!sna_crtc->kmode.clock) {
+		ERR(("%s(CRTC:%d [pipe=%d]): attempted to set an invalid mode\n",
+		     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc)));
+		return EINVAL;
+	}
+
+	kmsg_open(&kmsg);
+	sigio = sigio_block();
+
+	assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
+	sna_crtc_disable_cursor(sna, sna_crtc);
+
+	if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) {
+		memset(&arg, 0, sizeof(arg));
+		arg.crtc_id = __sna_crtc_id(sna_crtc);
+		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
+	}
+
+	if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) {
+		ERR(("%s: set-primary-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n",
+		     __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno));
+		sna_crtc->primary.rotation.supported &= ~sna_crtc->rotation;
+		goto unblock;
+	}
+	DBG(("%s: CRTC:%d [pipe=%d] primary rotation set to %x\n",
+	     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), sna_crtc->rotation));
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+
+		/* Make sure we mark the output as off (and save the backlight)
+		 * before the kernel turns it off due to changing the pipe.
+		 * This is necessary as the kernel may turn off the backlight
+		 * and we lose track of the user settings.
+		 */
+		if (output->crtc == NULL)
+			__sna_output_dpms(output, DPMSModeOff, false);
+
+		if (output->crtc != crtc)
+			continue;
+
+		/* Skip over any hotunplugged outputs so that we can
+		 * recover in cases where the previous mode is now
+		 * only partially valid.
+		 */
+		if (!to_sna_output(output)->id)
+			continue;
+
+		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
+		     __FUNCTION__, output->name, i, to_connector_id(output),
+		     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
+		     (uint32_t)output->possible_crtcs,
+		     (uint32_t)output->possible_clones));
+
+		assert(output->possible_crtcs & (1 << __sna_crtc_pipe(sna_crtc)) ||
+		       is_zaphod(crtc->scrn));
+
+		output_ids[output_count] = to_connector_id(output);
+		if (++output_count == ARRAY_SIZE(output_ids)) {
+			DBG(("%s: too many outputs (%d) for me!\n",
+			     __FUNCTION__, output_count));
+			goto unblock;
+		}
+	}
+	if (output_count == 0) {
+		DBG(("%s: no outputs\n", __FUNCTION__));
+		goto unblock;
+	}
+
+	VG_CLEAR(arg);
+	arg.crtc_id = __sna_crtc_id(sna_crtc);
+	arg.fb_id = fb_id(sna_crtc->bo);
+	if (sna_crtc->transform || sna_crtc->slave_pixmap) {
+		arg.x = 0;
+		arg.y = 0;
+		sna_crtc->offset = 0;
+	} else {
+		arg.x = crtc->x;
+		arg.y = crtc->y;
+		sna_crtc->offset = arg.y << 16 | arg.x;
+	}
+	arg.set_connectors_ptr = (uintptr_t)output_ids;
+	arg.count_connectors = output_count;
+	arg.mode = sna_crtc->kmode;
+	arg.mode_valid = 1;
+
+	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d%s%s update to %d outputs [%d...]\n",
+	     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
+	     arg.mode.hdisplay,
+	     arg.mode.vdisplay,
+	     arg.x, arg.y,
+	     arg.mode.clock,
+	     arg.fb_id,
+	     sna_crtc->shadow ? " [shadow]" : "",
+	     sna_crtc->transform ? " [transformed]" : "",
+	     output_count, output_count ? output_ids[0] : 0));
+
+	ret = 0;
+	if (unlikely(drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))) {
+		ret = errno;
+		goto unblock;
+	}
+
+	sna_crtc->mode_serial++;
+	sna_crtc_force_outputs_on(crtc);
+
+unblock:
+	sigio_unblock(sigio);
+	kmsg_close(&kmsg, ret);
+	return ret;
+}
+
+static bool overlap(const BoxRec *a, const BoxRec *b)
+{
+	if (a->x1 >= b->x2)
+		return false;
+	if (a->x2 <= b->x1)
+		return false;
+
+	if (a->y1 >= b->y2)
+		return false;
+	if (a->y2 <= b->y1)
+		return false;
+
+	return true;
+}
+
+static void defer_event(struct sna *sna, struct drm_event *base)
+{
+	if (sna->mode.shadow_nevent == sna->mode.shadow_size) {
+		int size = sna->mode.shadow_size * 2;
+		void *ptr;
+
+		ptr = realloc(sna->mode.shadow_events,
+			      sizeof(struct drm_event_vblank)*size);
+		if (!ptr)
+			return;
+
+		sna->mode.shadow_events = ptr;
+		sna->mode.shadow_size = size;
+	}
+
+	memcpy(&sna->mode.shadow_events[sna->mode.shadow_nevent++],
+	       base, sizeof(struct drm_event_vblank));
+	DBG(("%s: deferring event count=%d\n",
+	     __func__, sna->mode.shadow_nevent));
+}
+
+static void flush_events(struct sna *sna)
+{
+	int n;
+
+	if (!sna->mode.shadow_nevent)
+		return;
+
+	DBG(("%s: flushing %d events=%d\n", __func__, sna->mode.shadow_nevent));
+
+	for (n = 0; n < sna->mode.shadow_nevent; n++) {
+		struct drm_event_vblank *vb = &sna->mode.shadow_events[n];
+
+		if ((uintptr_t)(vb->user_data) & 2)
+			sna_present_vblank_handler(vb);
+		else
+			sna_dri2_vblank_handler(vb);
+	}
+
+	sna->mode.shadow_nevent = 0;
+}
+
+
+static bool wait_for_shadow(struct sna *sna,
+			    struct sna_pixmap *priv,
+			    unsigned flags)
+{
+	PixmapPtr pixmap = priv->pixmap;
+	struct kgem_bo *bo, *tmp;
+	int flip_active;
+	bool ret = true;
+
+	DBG(("%s: enabled? %d flags=%x, flips=%d, pixmap=%ld [front?=%d], handle=%d, shadow=%d\n",
+	     __FUNCTION__, sna->mode.shadow_enabled,
+	     flags, sna->mode.flip_active,
+	     pixmap->drawable.serialNumber, pixmap == sna->front,
+	     priv->gpu_bo->handle, sna->mode.shadow->handle));
+
+	assert(priv->move_to_gpu_data == sna);
+	assert(sna->mode.shadow != priv->gpu_bo);
+
+	if (flags == 0 || pixmap != sna->front || !sna->mode.shadow_enabled)
+		goto done;
+
+	assert(sna->mode.shadow_damage);
+
+	if ((flags & MOVE_WRITE) == 0) {
+		if ((flags & __MOVE_SCANOUT) == 0) {
+			struct sna_crtc *crtc;
+
+			list_for_each_entry(crtc, &sna->mode.shadow_crtc, shadow_link) {
+				if (overlap(&sna->mode.shadow_region.extents,
+					    &crtc->base->bounds)) {
+					DrawableRec draw;
+					RegionRec region;
+
+					draw.width = crtc->base->mode.HDisplay;
+					draw.height = crtc->base->mode.VDisplay;
+					draw.depth = sna->front->drawable.depth;
+					draw.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+					DBG(("%s: copying replaced CRTC: (%d, %d), (%d, %d), handle=%d\n",
+					     __FUNCTION__,
+					     crtc->base->bounds.x1,
+					     crtc->base->bounds.y1,
+					     crtc->base->bounds.x2,
+					     crtc->base->bounds.y2,
+					     crtc->client_bo->handle));
+
+					ret &= sna->render.copy_boxes(sna, GXcopy,
+								      &draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+								      &pixmap->drawable, priv->gpu_bo, 0, 0,
+								      &crtc->base->bounds, 1,
+								      0);
+
+					region.extents = crtc->base->bounds;
+					region.data = NULL;
+					RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, &region);
+				}
+			}
+		}
+
+		return ret;
+	}
+
+	assert(sna->mode.shadow_active);
+
+	flip_active = sna->mode.flip_active;
+	if (flip_active) {
+		struct sna_crtc *crtc;
+		list_for_each_entry(crtc, &sna->mode.shadow_crtc, shadow_link)
+			flip_active -= crtc->flip_pending;
+		DBG(("%s: %d flips still pending, shadow flip_active=%d\n",
+		     __FUNCTION__, sna->mode.flip_active, flip_active));
+	}
+
+	bo = sna->mode.shadow;
+	if (flip_active) {
+		bo = kgem_create_2d(&sna->kgem,
+				    pixmap->drawable.width,
+				    pixmap->drawable.height,
+				    pixmap->drawable.bitsPerPixel,
+				    priv->gpu_bo->tiling,
+				    CREATE_EXACT | CREATE_SCANOUT);
+		if (bo == NULL)
+			return false;
+
+		DBG(("%s: replacing still-attached GPU bo handle=%d, flips=%d\n",
+		     __FUNCTION__, priv->gpu_bo->tiling, sna->mode.flip_active));
+
+		RegionUninit(&sna->mode.shadow_region);
+		sna->mode.shadow_region.extents.x1 = 0;
+		sna->mode.shadow_region.extents.y1 = 0;
+		sna->mode.shadow_region.extents.x2 = pixmap->drawable.width;
+		sna->mode.shadow_region.extents.y2 = pixmap->drawable.height;
+		sna->mode.shadow_region.data = NULL;
+	}
+
+	if (bo->refcnt > 1) {
+		bo = kgem_create_2d(&sna->kgem,
+				    pixmap->drawable.width,
+				    pixmap->drawable.height,
+				    pixmap->drawable.bitsPerPixel,
+				    priv->gpu_bo->tiling,
+				    CREATE_EXACT | CREATE_SCANOUT);
+		if (bo != NULL) {
+			DBG(("%s: replacing exported GPU bo\n",
+			     __FUNCTION__));
+
+			RegionUninit(&sna->mode.shadow_region);
+			sna->mode.shadow_region.extents.x1 = 0;
+			sna->mode.shadow_region.extents.y1 = 0;
+			sna->mode.shadow_region.extents.x2 = pixmap->drawable.width;
+			sna->mode.shadow_region.extents.y2 = pixmap->drawable.height;
+			sna->mode.shadow_region.data = NULL;
+		} else
+			bo = sna->mode.shadow;
+	}
+
+	RegionSubtract(&sna->mode.shadow_region,
+		       &sna->mode.shadow_region,
+		       &sna->mode.shadow_cancel);
+
+	while (!list_is_empty(&sna->mode.shadow_crtc)) {
+		struct sna_crtc *crtc =
+			list_first_entry(&sna->mode.shadow_crtc, struct sna_crtc, shadow_link);
+		if (overlap(&crtc->base->bounds,
+			    &sna->mode.shadow_region.extents)) {
+			RegionRec region;
+			DrawableRec draw;
+
+			draw.width = crtc->base->mode.HDisplay;
+			draw.height = crtc->base->mode.VDisplay;
+			draw.depth = sna->front->drawable.depth;
+			draw.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+			DBG(("%s: copying replaced CRTC: (%d, %d), (%d, %d), handle=%d\n",
+			     __FUNCTION__,
+			     crtc->base->bounds.x1,
+			     crtc->base->bounds.y1,
+			     crtc->base->bounds.x2,
+			     crtc->base->bounds.y2,
+			     crtc->client_bo->handle));
+
+			ret = sna->render.copy_boxes(sna, GXcopy,
+						     &draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+						     &pixmap->drawable, bo, 0, 0,
+						     &crtc->base->bounds, 1,
+						     0);
+
+
+			region.extents = crtc->base->bounds;
+			region.data = NULL;
+			RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, &region);
+		}
+
+		crtc->client_bo->active_scanout--;
+		kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+		crtc->client_bo = NULL;
+		list_del(&crtc->shadow_link);
+	}
+
+	if (RegionNotEmpty(&sna->mode.shadow_region)) {
+		DBG(("%s: copying existing GPU damage: %dx(%d, %d), (%d, %d)\n",
+		     __FUNCTION__, region_num_rects(&sna->mode.shadow_region),
+		     sna->mode.shadow_region.extents.x1,
+		     sna->mode.shadow_region.extents.y1,
+		     sna->mode.shadow_region.extents.x2,
+		     sna->mode.shadow_region.extents.y2));
+		if (!sna->render.copy_boxes(sna, GXcopy,
+					    &pixmap->drawable, priv->gpu_bo, 0, 0,
+					    &pixmap->drawable, bo, 0, 0,
+					    region_rects(&sna->mode.shadow_region),
+					    region_num_rects(&sna->mode.shadow_region),
+					    0))
+			ERR(("%s: copy failed\n", __FUNCTION__));
+	}
+
+	if (priv->cow)
+		sna_pixmap_undo_cow(sna, priv, 0);
+
+	sna_pixmap_unmap(pixmap, priv);
+
+	DBG(("%s: setting front pixmap to handle=%d\n", __FUNCTION__, bo->handle));
+	assert(sna->mode.shadow->active_scanout);
+	sna->mode.shadow->active_scanout--;
+	tmp = priv->gpu_bo;
+	priv->gpu_bo = bo;
+	if (bo != sna->mode.shadow)
+		kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
+	sna->mode.shadow = tmp;
+	sna->mode.shadow->active_scanout++;
+	assert(sna->mode.shadow->active_scanout);
+
+	sna_dri2_pixmap_update_bo(sna, pixmap, bo);
+
+done:
+	RegionEmpty(&sna->mode.shadow_cancel);
+	RegionEmpty(&sna->mode.shadow_region);
+	sna->mode.shadow_dirty = false;
+
+	priv->move_to_gpu_data = NULL;
+	priv->move_to_gpu = NULL;
+
+	assert(sna->mode.shadow->active_scanout);
+	return ret;
+}
+
+bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
+				      const RegionRec *region)
+{
+	struct sna *sna;
+
+	if (priv->move_to_gpu != wait_for_shadow)
+		return false;
+
+	sna = priv->move_to_gpu_data;
+	if (region) {
+		DBG(("%s: discarding region %dx[(%d, %d), (%d, %d)] from damage %dx[(%d, %d], (%d, %d)]\n",
+		     __FUNCTION__,
+		     region_num_rects(region),
+		     region->extents.x1, region->extents.y1,
+		     region->extents.x2, region->extents.y2,
+		     region_num_rects(&sna->mode.shadow_region),
+		     sna->mode.shadow_region.extents.x1, sna->mode.shadow_region.extents.y1,
+		     sna->mode.shadow_region.extents.x2, sna->mode.shadow_region.extents.y2));
+
+		RegionSubtract(&sna->mode.shadow_region,
+			       &sna->mode.shadow_region,
+			       (RegionPtr)region);
+		RegionUnion(&sna->mode.shadow_cancel,
+			    &sna->mode.shadow_cancel,
+			    (RegionPtr)region);
+	} else {
+		DBG(("%s: discarding all damage %dx[(%d, %d], (%d, %d)]\n",
+		     __FUNCTION__,
+		     region_num_rects(&sna->mode.shadow_region),
+		     sna->mode.shadow_region.extents.x1, sna->mode.shadow_region.extents.y1,
+		     sna->mode.shadow_region.extents.x2, sna->mode.shadow_region.extents.y2));
+		RegionEmpty(&sna->mode.shadow_region);
+
+		RegionUninit(&sna->mode.shadow_cancel);
+		sna->mode.shadow_cancel.extents.x1 = 0;
+		sna->mode.shadow_cancel.extents.y1 = 0;
+		sna->mode.shadow_cancel.extents.x2 = sna->front->drawable.width;
+		sna->mode.shadow_cancel.extents.y2 = sna->front->drawable.height;
+		sna->mode.shadow_cancel.data = NULL;
+	}
+
+	return RegionNil(&sna->mode.shadow_region);
+}
+
+static void sna_mode_damage(DamagePtr damage, RegionPtr region, void *closure)
+{
+	struct sna *sna = closure;
+
+	if (sna->mode.rr_active)
+		return;
+
+	/* Throw away the rectangles if the region grows too big */
+	region = DamageRegion(damage);
+	if (region->data) {
+		RegionRec dup;
+
+		dup = *region;
+		RegionUninit(&dup);
+
+		region->data = NULL;
+	}
+}
+
+static bool sna_mode_enable_shadow(struct sna *sna)
+{
+	ScreenPtr screen = to_screen_from_sna(sna);
+
+	DBG(("%s\n", __FUNCTION__));
+	assert(sna->mode.shadow == NULL);
+	assert(sna->mode.shadow_damage == NULL);
+	assert(sna->mode.shadow_active == 0);
+	assert(!sna->mode.shadow_enabled);
+
+	sna->mode.shadow_damage = DamageCreate(sna_mode_damage, NULL,
+					       DamageReportRawRegion,
+					       TRUE, screen, sna);
+	if (!sna->mode.shadow_damage)
+		return false;
+
+	DamageRegister(&sna->front->drawable, sna->mode.shadow_damage);
+	sna->mode.shadow_enabled = true;
+	return true;
+}
+
+static void sna_mode_disable_shadow(struct sna *sna)
+{
+	struct sna_pixmap *priv;
+
+	if (!sna->mode.shadow_damage) {
+		assert(!sna->mode.shadow_enabled);
+		return;
+	}
+
+	DBG(("%s\n", __FUNCTION__));
+
+	priv = sna_pixmap(sna->front);
+	if (priv->move_to_gpu == wait_for_shadow)
+		priv->move_to_gpu(sna, priv, 0);
+
+	DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage);
+	DamageDestroy(sna->mode.shadow_damage);
+	sna->mode.shadow_damage = NULL;
+	sna->mode.shadow_enabled = false;
+
+	if (sna->mode.shadow) {
+		sna->mode.shadow->active_scanout--;
+		kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
+		sna->mode.shadow = NULL;
+	}
+
+	assert(sna->mode.shadow_active == 0);
+	sna->mode.shadow_dirty = false;
+}
+
+static void sna_crtc_slave_damage(DamagePtr damage, RegionPtr region, void *closure)
+{
+	struct sna_crtc *crtc = closure;
+	struct sna *sna = to_sna(crtc->base->scrn);
+	RegionPtr scr;
+
+	DBG(("%s: pushing damage [(%d, %d), (%d, %d) x %d] to CRTC [pipe=%d] (%d, %d)\n",
+	     __FUNCTION__,
+	     region->extents.x1, region->extents.y1, region->extents.x2, region->extents.y2,
+	     region_num_rects(region),
+	     __sna_crtc_pipe(crtc), crtc->base->x, crtc->base->y));
+
+	assert(crtc->slave_damage == damage);
+	assert(sna->mode.shadow_damage);
+
+	RegionTranslate(region, crtc->base->x, crtc->base->y);
+	scr = DamageRegion(sna->mode.shadow_damage);
+	RegionUnion(scr, scr, region);
+	RegionTranslate(region, -crtc->base->x, -crtc->base->y);
+}
+
+static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
+{
+	if (crtc->shadow) {
+		assert(sna->mode.shadow_damage && sna->mode.shadow_active);
+		return true;
+	}
+
+	DBG(("%s: enabling for crtc %d\n", __FUNCTION__, __sna_crtc_id(crtc)));
+
+	if (!sna->mode.shadow_active) {
+		if (!sna_mode_enable_shadow(sna))
+			return false;
+		assert(sna->mode.shadow_damage);
+		assert(sna->mode.shadow == NULL);
+	}
+
+	if (crtc->slave_pixmap) {
+		assert(crtc->slave_damage == NULL);
+
+		DBG(("%s: enabling PRIME slave tracking on CRTC %d [pipe=%d], pixmap=%ld\n",
+		     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->slave_pixmap->drawable.serialNumber));
+		crtc->slave_damage = DamageCreate(sna_crtc_slave_damage, NULL,
+						  DamageReportRawRegion, TRUE,
+						  to_screen_from_sna(sna),
+						  crtc);
+		if (crtc->slave_damage == NULL) {
+			if (!--sna->mode.shadow_active)
+				sna_mode_disable_shadow(sna);
+			return false;
+		}
+
+		DamageRegister(&crtc->slave_pixmap->drawable, crtc->slave_damage);
+	}
+
+	crtc->shadow = true;
+	sna->mode.shadow_active++;
+	return true;
+}
+
+static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
+{
+	if (crtc->client_bo == NULL)
+		return;
+
+	assert(crtc->client_bo->refcnt >= crtc->client_bo->active_scanout);
+	crtc->client_bo->active_scanout--;
+
+	if (!crtc->transform) {
+		DrawableRec tmp;
+
+		tmp.width = crtc->base->mode.HDisplay;
+		tmp.height = crtc->base->mode.VDisplay;
+		tmp.depth = sna->front->drawable.depth;
+		tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+		sna->render.copy_boxes(sna, GXcopy,
+				       &tmp, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+				       &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
+				       &crtc->base->bounds, 1, 0);
+		list_del(&crtc->shadow_link);
+	}
+	kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+	crtc->client_bo = NULL;
+}
+
+static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
+{
+	crtc->fallback_shadow = false;
+	if (!crtc->shadow)
+		return;
+
+	DBG(("%s: disabling for crtc %d\n", __FUNCTION__, __sna_crtc_id(crtc)));
+	assert(sna->mode.shadow_active > 0);
+
+	if (crtc->slave_damage) {
+		assert(crtc->slave_pixmap);
+		DamageUnregister(&crtc->slave_pixmap->drawable, crtc->slave_damage);
+		DamageDestroy(crtc->slave_damage);
+		crtc->slave_damage = NULL;
+	}
+
+	sna_crtc_disable_override(sna, crtc);
+
+	if (!--sna->mode.shadow_active)
+		sna_mode_disable_shadow(sna);
+
+	crtc->shadow = false;
+}
+
+static void
+__sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
+{
+	sna_crtc->mode_serial++;
+
+	sna_crtc_disable_cursor(sna, sna_crtc);
+	rotation_set(sna, &sna_crtc->primary, RR_Rotate_0);
+	sna_crtc_disable_shadow(sna, sna_crtc);
+
+	if (sna_crtc->bo) {
+		DBG(("%s: releasing handle=%d from scanout, active=%d\n",
+		     __FUNCTION__,sna_crtc->bo->handle, sna_crtc->bo->active_scanout-1));
+		assert(sna_crtc->public.flags & CRTC_ON);
+		assert(sna_crtc->bo->active_scanout);
+		assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
+		sna_crtc->bo->active_scanout--;
+		kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
+		sna_crtc->bo = NULL;
+		sna_crtc->public.flags &= ~CRTC_ON;
+
+		if (sna->mode.hidden) {
+			sna->mode.hidden--;
+			assert(sna->mode.hidden);
+			assert(sna->mode.front_active == 0);
+		} else {
+			assert(sna->mode.front_active);
+			sna->mode.front_active--;
+		}
+		sna->mode.dirty = true;
+	}
+
+	if (sna_crtc->shadow_bo) {
+		kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+		sna_crtc->shadow_bo = NULL;
+	}
+	if (sna_crtc->transform) {
+		assert(sna->mode.rr_active);
+		sna->mode.rr_active--;
+		sna_crtc->transform = false;
+	}
+
+	sna_crtc->cursor_transform = false;
+	sna_crtc->hwcursor = true;
+	assert(!sna_crtc->shadow);
+}
+
+static void
+sna_crtc_disable(xf86CrtcPtr crtc, bool force)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct drm_mode_crtc arg;
+
+	if (sna_crtc == NULL)
+		return;
+
+	if (!force && sna_crtc->bo == NULL)
+		return;
+
+	DBG(("%s: disabling crtc [%d, pipe=%d], force?=%d\n", __FUNCTION__,
+	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), force));
+
+	sna_crtc_force_outputs_off(crtc);
+
+	memset(&arg, 0, sizeof(arg));
+	arg.crtc_id = __sna_crtc_id(sna_crtc);
+	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
+
+	__sna_crtc_disable(sna, sna_crtc);
+}
+
+static void update_flush_interval(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i, max_vrefresh = 0;
+
+	DBG(("%s: front_active=%d\n", __FUNCTION__, sna->mode.front_active));
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		assert(to_sna_crtc(crtc) != NULL);
+
+		if (!crtc->enabled) {
+			DBG(("%s: CRTC:%d (pipe %d) disabled\n",
+			     __FUNCTION__,i, sna_crtc_pipe(crtc)));
+			assert(to_sna_crtc(crtc)->bo == NULL);
+			continue;
+		}
+
+		if (to_sna_crtc(crtc)->bo == NULL) {
+			DBG(("%s: CRTC:%d (pipe %d) turned off\n",
+			     __FUNCTION__,i, sna_crtc_pipe(crtc)));
+			continue;
+		}
+
+		DBG(("%s: CRTC:%d (pipe %d) vrefresh=%f\n",
+		     __FUNCTION__, i, sna_crtc_pipe(crtc),
+		     xf86ModeVRefresh(&crtc->mode)));
+		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(&crtc->mode));
+	}
+
+	if (max_vrefresh == 0) {
+		assert(sna->mode.front_active == 0);
+		sna->vblank_interval = 0;
+	} else
+		sna->vblank_interval = 1000 / max_vrefresh; /* Hz -> ms */
+
+	DBG(("max_vrefresh=%d, vblank_interval=%d ms\n",
+	       max_vrefresh, sna->vblank_interval));
+}
+
+static struct kgem_bo *sna_create_bo_for_fbcon(struct sna *sna,
+					       const struct drm_mode_fb_cmd *fbcon)
+{
+	struct drm_gem_flink flink;
+	struct kgem_bo *bo;
+	int ret;
+
+	/* Create a new reference for the fbcon so that we can track it
+	 * using a normal bo and so that when we call gem_close on it we
+	 * delete our reference and not fbcon's!
+	 */
+	VG_CLEAR(flink);
+	flink.handle = fbcon->handle;
+	ret = drmIoctl(sna->kgem.fd, DRM_IOCTL_GEM_FLINK, &flink);
+	if (ret)
+		return NULL;
+
+	bo = kgem_create_for_name(&sna->kgem, flink.name);
+	if (bo == NULL)
+		return NULL;
+
+	bo->pitch = fbcon->pitch;
+	return bo;
+}
+
+/* Copy the current framebuffer contents into the front-buffer for a seamless
+ * transition from e.g. plymouth.
+ */
+void sna_copy_fbcon(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	struct drm_mode_fb_cmd fbcon;
+	PixmapRec scratch;
+	struct sna_pixmap *priv;
+	struct kgem_bo *bo;
+	BoxRec box;
+	bool ok;
+	int sx, sy;
+	int dx, dy;
+	int i;
+
+	if (wedged(sna) || isGPU(sna->scrn))
+		return;
+
+	DBG(("%s\n", __FUNCTION__));
+	assert((sna->flags & SNA_IS_HOSTED) == 0);
+
+	priv = sna_pixmap_move_to_gpu(sna->front, MOVE_WRITE | __MOVE_SCANOUT);
+	if (priv == NULL)
+		return;
+
+	/* Scan the connectors for a framebuffer and assume that is the fbcon */
+	VG_CLEAR(fbcon);
+	fbcon.fb_id = 0;
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *crtc = to_sna_crtc(config->crtc[i]);
+		struct drm_mode_crtc mode;
+
+		assert(crtc != NULL);
+
+		VG_CLEAR(mode);
+		mode.crtc_id = __sna_crtc_id(crtc);
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
+			continue;
+		if (!mode.fb_id)
+			continue;
+
+		fbcon.fb_id = mode.fb_id;
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETFB, &fbcon)) {
+			fbcon.fb_id = 0;
+			continue;
+		}
+		break;
+	}
+	if (fbcon.fb_id == 0) {
+		DBG(("%s: no fbcon found\n", __FUNCTION__));
+		return;
+	}
+
+	if (fbcon.fb_id == fb_id(priv->gpu_bo)) {
+		DBG(("%s: fb already installed as scanout\n", __FUNCTION__));
+		return;
+	}
+
+	DBG(("%s: found fbcon, size=%dx%d, depth=%d, bpp=%d\n",
+	     __FUNCTION__, fbcon.width, fbcon.height, fbcon.depth, fbcon.bpp));
+
+	bo = sna_create_bo_for_fbcon(sna, &fbcon);
+	if (bo == NULL)
+		return;
+
+	DBG(("%s: fbcon handle=%d\n", __FUNCTION__, bo->handle));
+
+	scratch.drawable.width = fbcon.width;
+	scratch.drawable.height = fbcon.height;
+	scratch.drawable.depth = fbcon.depth;
+	scratch.drawable.bitsPerPixel = fbcon.bpp;
+	scratch.devPrivate.ptr = NULL;
+
+	box.x1 = box.y1 = 0;
+	box.x2 = min(fbcon.width, sna->front->drawable.width);
+	box.y2 = min(fbcon.height, sna->front->drawable.height);
+
+	sx = dx = 0;
+	if (box.x2 < (uint16_t)fbcon.width)
+		sx = (fbcon.width - box.x2) / 2;
+	if (box.x2 < sna->front->drawable.width)
+		dx = (sna->front->drawable.width - box.x2) / 2;
+
+	sy = dy = 0;
+	if (box.y2 < (uint16_t)fbcon.height)
+		sy = (fbcon.height - box.y2) / 2;
+	if (box.y2 < sna->front->drawable.height)
+		dy = (sna->front->drawable.height - box.y2) / 2;
+
+	ok = sna->render.copy_boxes(sna, GXcopy,
+				    &scratch.drawable, bo, sx, sy,
+				    &sna->front->drawable, priv->gpu_bo, dx, dy,
+				    &box, 1, 0);
+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
+		sna_damage_add_box(&priv->gpu_damage, &box);
+
+	kgem_bo_destroy(&sna->kgem, bo);
+
+#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
+	to_screen_from_sna(sna)->canDoBGNoneRoot = ok;
+#endif
+}
+
+static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
+{
+	RRTransformPtr transform;
+	PictTransform crtc_to_fb;
+	struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
+	unsigned pitch_limit;
+	BoxRec b;
+
+	assert(sna->scrn->virtualX && sna->scrn->virtualY);
+
+	if (sna->flags & SNA_FORCE_SHADOW) {
+		DBG(("%s: forcing shadow\n", __FUNCTION__));
+		return true;
+	}
+
+	if (to_sna_crtc(crtc)->fallback_shadow) {
+		DBG(("%s: fallback shadow\n", __FUNCTION__));
+		return true;
+	}
+
+	if (sna->flags & SNA_TEAR_FREE && to_sna_crtc(crtc)->slave_pixmap) {
+		DBG(("%s: TearFree shadow required\n", __FUNCTION__));
+		return true;
+	}
+
+	if (sna->scrn->virtualX > sna->mode.max_crtc_width ||
+	    sna->scrn->virtualY > sna->mode.max_crtc_height) {
+		DBG(("%s: framebuffer too large (%dx%d) > (%dx%d)\n",
+		    __FUNCTION__,
+		    sna->scrn->virtualX, sna->scrn->virtualY,
+		    sna->mode.max_crtc_width, sna->mode.max_crtc_height));
+		return true;
+	}
+
+	if (!isGPU(sna->scrn)) {
+		struct sna_pixmap *priv;
+
+		priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
+		if (priv == NULL)
+			return true; /* maybe we can create a bo for the scanout? */
+
+		if (sna->kgem.gen == 071)
+			pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
+		else if ((sna->kgem.gen >> 3) > 4)
+			pitch_limit = 32 * 1024;
+		else if ((sna->kgem.gen >> 3) == 4)
+			pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
+		else if ((sna->kgem.gen >> 3) == 3)
+			pitch_limit = priv->gpu_bo->tiling ? 8 * 1024 : 16 * 1024;
+		else
+			pitch_limit = 8 * 1024;
+		DBG(("%s: gpu bo handle=%d tiling=%d pitch=%d, limit=%d\n", __FUNCTION__, priv->gpu_bo->handle, priv->gpu_bo->tiling, priv->gpu_bo->pitch, pitch_limit));
+		if (priv->gpu_bo->pitch > pitch_limit)
+			return true;
+
+		if (priv->gpu_bo->tiling && sna->flags & SNA_LINEAR_FB) {
+			DBG(("%s: gpu bo is tiled, need linear, forcing shadow\n", __FUNCTION__));
+			return true;
+		}
+	}
+
+	transform = NULL;
+	if (crtc->transformPresent)
+		transform = &crtc->transform;
+	if (RRTransformCompute(crtc->x, crtc->y,
+			       crtc->mode.HDisplay, crtc->mode.VDisplay,
+			       crtc->rotation, transform,
+			       &crtc_to_fb,
+			       &f_crtc_to_fb,
+			       &f_fb_to_crtc)) {
+		bool needs_transform = true;
+		unsigned rotation = rotation_reduce(&to_sna_crtc(crtc)->primary, crtc->rotation);
+		DBG(("%s: natively supported rotation? rotation=%x & supported=%x == %d\n",
+		     __FUNCTION__, rotation, to_sna_crtc(crtc)->primary.rotation.supported,
+		     rotation == (rotation & to_sna_crtc(crtc)->primary.rotation.supported)));
+		if ((to_sna_crtc(crtc)->primary.rotation.supported & rotation) == rotation)
+			needs_transform = RRTransformCompute(crtc->x, crtc->y,
+							     crtc->mode.HDisplay, crtc->mode.VDisplay,
+							     RR_Rotate_0, transform,
+							     NULL, NULL, NULL);
+		if (needs_transform) {
+			DBG(("%s: RandR transform present\n", __FUNCTION__));
+			return true;
+		}
+	}
+
+	/* And finally check that it is entirely visible */
+	b.x1 = b.y1 = 0;
+	b.x2 = crtc->mode.HDisplay;
+	b.y2 = crtc->mode.VDisplay;
+	pixman_f_transform_bounds(&f_crtc_to_fb, &b);
+	DBG(("%s? bounds (%d, %d), (%d, %d), framebufer %dx%d\n",
+	     __FUNCTION__, b.x1, b.y1, b.x2, b.y2,
+		 sna->scrn->virtualX, sna->scrn->virtualY));
+
+	if  (b.x1 < 0 || b.y1 < 0 ||
+	     b.x2 > sna->scrn->virtualX ||
+	     b.y2 > sna->scrn->virtualY) {
+		DBG(("%s: scanout is partly outside the framebuffer\n",
+		     __FUNCTION__));
+		return true;
+	}
+
+	return false;
+}
+
+static void set_shadow(struct sna *sna, RegionPtr region)
+{
+	struct sna_pixmap *priv = sna_pixmap(sna->front);
+
+	assert(priv->gpu_bo);
+	assert(sna->mode.shadow);
+	assert(sna->mode.shadow->active_scanout);
+
+	DBG(("%s: waiting for region %dx[(%d, %d), (%d, %d)], front handle=%d, shadow handle=%d\n",
+	     __FUNCTION__,
+	     region_num_rects(region),
+	     region->extents.x1, region->extents.y1,
+	     region->extents.x2, region->extents.y2,
+	     priv->gpu_bo->handle, sna->mode.shadow->handle));
+
+	assert(priv->pinned & PIN_SCANOUT);
+	assert((priv->pinned & PIN_PRIME) == 0);
+	assert(sna->mode.shadow != priv->gpu_bo);
+
+	RegionCopy(&sna->mode.shadow_region, region);
+
+	priv->move_to_gpu = wait_for_shadow;
+	priv->move_to_gpu_data = sna;
+}
+
+static struct kgem_bo *
+get_scanout_bo(struct sna *sna, PixmapPtr pixmap)
+{
+	struct sna_pixmap *priv;
+
+	priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT);
+	if (!priv)
+		return NULL;
+
+	if (priv->gpu_bo->pitch & 63) {
+		struct kgem_bo *tmp;
+		BoxRec b;
+
+		DBG(("%s: converting to scanout bo due to bad pitch [%d]\n",
+		     __FUNCTION__, priv->gpu_bo->pitch));
+
+		if (priv->pinned) {
+			DBG(("%s: failed as the Pixmap is already pinned [%x]\n",
+			     __FUNCTION__, priv->pinned));
+			return NULL;
+		}
+
+		tmp = kgem_create_2d(&sna->kgem,
+				     pixmap->drawable.width,
+				     pixmap->drawable.height,
+				     sna->scrn->bitsPerPixel,
+				     priv->gpu_bo->tiling,
+				     CREATE_EXACT | CREATE_SCANOUT);
+		if (tmp == NULL) {
+			DBG(("%s: allocation failed\n", __FUNCTION__));
+			return NULL;
+		}
+
+		b.x1 = 0;
+		b.y1 = 0;
+		b.x2 = pixmap->drawable.width;
+		b.y2 = pixmap->drawable.height;
+
+		if (sna->render.copy_boxes(sna, GXcopy,
+					   &pixmap->drawable, priv->gpu_bo, 0, 0,
+					   &pixmap->drawable, tmp, 0, 0,
+					   &b, 1, COPY_LAST)) {
+			DBG(("%s: copy failed\n", __FUNCTION__));
+			kgem_bo_destroy(&sna->kgem, tmp);
+			return NULL;
+		}
+
+		kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+		priv->gpu_bo = tmp;
+	}
+
+	priv->pinned |= PIN_SCANOUT;
+	return priv->gpu_bo;
+}
+
+static void shadow_clear(struct sna *sna,
+			 PixmapPtr front, struct kgem_bo *bo,
+			 xf86CrtcPtr crtc)
+{
+	bool ok = false;
+	if (!wedged(sna))
+		ok = sna->render.fill_one(sna, front, bo, 0,
+					  0, 0, crtc->mode.HDisplay, crtc->mode.VDisplay,
+					  GXclear);
+	if (!ok) {
+		void *ptr = kgem_bo_map__gtt(&sna->kgem, bo);
+		if (ptr)
+			memset(ptr, 0, bo->pitch * crtc->mode.VDisplay);
+	}
+	sna->mode.shadow_dirty = true;
+}
+
+static bool rr_active(xf86CrtcPtr crtc)
+{
+	return crtc->transformPresent || crtc->rotation != RR_Rotate_0;
+}
+
+static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	ScrnInfoPtr scrn = crtc->scrn;
+	struct sna *sna = to_sna(scrn);
+	struct kgem_bo *bo;
+
+	if (sna_crtc->transform) {
+		assert(sna->mode.rr_active);
+		sna_crtc->transform = false;
+		sna->mode.rr_active--;
+	}
+	sna_crtc->rotation = RR_Rotate_0;
+
+	if (sna_crtc->cache_bo) {
+		kgem_bo_destroy(&sna->kgem, sna_crtc->cache_bo);
+		sna_crtc->cache_bo = NULL;
+	}
+
+	if (use_shadow(sna, crtc)) {
+		PixmapPtr front;
+		unsigned long tiled_limit;
+		int tiling;
+
+force_shadow:
+		if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
+			DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
+			return NULL;
+		}
+
+		DBG(("%s: attaching to per-crtc pixmap %dx%d\n",
+		     __FUNCTION__, crtc->mode.HDisplay, crtc->mode.VDisplay));
+
+		bo = sna_crtc->shadow_bo;
+		if (bo) {
+			if (sna_crtc->shadow_bo_width == crtc->mode.HDisplay &&
+			    sna_crtc->shadow_bo_height == crtc->mode.VDisplay) {
+				DBG(("%s: reusing current shadow bo handle=%d\n",
+				     __FUNCTION__, bo->handle));
+				goto out_shadow;
+			}
+
+			kgem_bo_destroy(&sna->kgem, bo);
+			sna_crtc->shadow_bo = NULL;
+		}
+
+		tiling = I915_TILING_X;
+		if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270) &&
+		    sna->kgem.can_scanout_y)
+			tiling = I915_TILING_Y;
+
+		if (sna->kgem.gen == 071)
+			tiled_limit = 16 * 1024 * 8;
+		else if ((sna->kgem.gen >> 3) > 4)
+			tiled_limit = 32 * 1024 * 8;
+		else if ((sna->kgem.gen >> 3) == 4)
+			tiled_limit = 16 * 1024 * 8;
+		else
+			tiled_limit = 8 * 1024 * 8;
+		if ((unsigned long)crtc->mode.HDisplay * scrn->bitsPerPixel > tiled_limit)
+			tiling = I915_TILING_NONE;
+		if (sna->flags & SNA_LINEAR_FB)
+			tiling = I915_TILING_NONE;
+
+		bo = kgem_create_2d(&sna->kgem,
+				    crtc->mode.HDisplay, crtc->mode.VDisplay,
+				    scrn->bitsPerPixel,
+				    tiling, CREATE_SCANOUT);
+		if (bo == NULL) {
+			DBG(("%s: failed to allocate crtc scanout\n", __FUNCTION__));
+			return NULL;
+		}
+
+		if (!get_fb(sna, bo, crtc->mode.HDisplay, crtc->mode.VDisplay)) {
+			DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
+			kgem_bo_destroy(&sna->kgem, bo);
+			return NULL;
+		}
+
+		front = sna_crtc->slave_pixmap ?: sna->front;
+		if (__sna_pixmap_get_bo(front) && !rr_active(crtc)) {
+			BoxRec b;
+
+			b.x1 = crtc->x;
+			b.y1 = crtc->y;
+			b.x2 = crtc->x + crtc->mode.HDisplay;
+			b.y2 = crtc->y + crtc->mode.VDisplay;
+
+			if (b.x1 < 0)
+				b.x1 = 0;
+			if (b.y1 < 0)
+				b.y1 = 0;
+			if (b.x2 > scrn->virtualX)
+				b.x2 = scrn->virtualX;
+			if (b.y2 > scrn->virtualY)
+				b.y2 = scrn->virtualY;
+			if (b.x2 - b.x1 < crtc->mode.HDisplay ||
+			    b.y2 - b.y1 < crtc->mode.VDisplay)
+				shadow_clear(sna, front, bo, crtc);
+
+			if (b.y2 > b.y1 && b.x2 > b.x1) {
+				DrawableRec tmp;
+
+				DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d) [fb=%dx%d], handle=%d\n",
+				     __FUNCTION__,
+				     b.x1, b.y1,
+				     b.x2-b.x1, b.y2-b.y1,
+				     scrn->virtualX, scrn->virtualY,
+				     bo->handle));
+
+				tmp.width = crtc->mode.HDisplay;
+				tmp.height = crtc->mode.VDisplay;
+				tmp.depth = front->drawable.depth;
+				tmp.bitsPerPixel = front->drawable.bitsPerPixel;
+
+				if (!sna->render.copy_boxes(sna, GXcopy,
+							     &front->drawable, __sna_pixmap_get_bo(front), 0, 0,
+							     &tmp, bo, -crtc->x, -crtc->y,
+							     &b, 1, COPY_LAST))
+					shadow_clear(sna, front, bo, crtc);
+			}
+		} else
+			shadow_clear(sna, front, bo, crtc);
+
+		sna_crtc->shadow_bo_width = crtc->mode.HDisplay;
+		sna_crtc->shadow_bo_height = crtc->mode.VDisplay;
+		sna_crtc->shadow_bo = bo;
+out_shadow:
+		sna_crtc->transform = true;
+		sna->mode.rr_active++;
+		return kgem_bo_reference(bo);
+	} else {
+		if (sna_crtc->shadow_bo) {
+			kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+			sna_crtc->shadow_bo = NULL;
+		}
+
+		if (sna_crtc->slave_pixmap) {
+			DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
+			bo = get_scanout_bo(sna, sna_crtc->slave_pixmap);
+			if (bo == NULL) {
+				DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__));
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
+			}
+
+			if (!get_fb(sna, bo,
+				    sna_crtc->slave_pixmap->drawable.width,
+				    sna_crtc->slave_pixmap->drawable.height)) {
+				DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
+			}
+		} else {
+			DBG(("%s: attaching to framebuffer\n", __FUNCTION__));
+			bo = get_scanout_bo(sna, sna->front);
+			if (bo == NULL) {
+				DBG(("%s: failed to pin framebuffer\n", __FUNCTION__));
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
+			}
+
+			if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY)) {
+				DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
+			}
+		}
+
+		if (sna->flags & SNA_TEAR_FREE) {
+			RegionRec region;
+
+			assert(sna_crtc->slave_pixmap == NULL);
+
+			DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
+			region.extents.x1 = 0;
+			region.extents.y1 = 0;
+			region.extents.x2 = sna->scrn->virtualX;
+			region.extents.y2 = sna->scrn->virtualY;
+			region.data = NULL;
+
+			if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
+				DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
+				return NULL;
+			}
+
+			if (sna->mode.shadow == NULL) {
+				struct kgem_bo *shadow;
+
+				DBG(("%s: creating TearFree shadow bo\n", __FUNCTION__));
+				shadow = kgem_create_2d(&sna->kgem,
+							region.extents.x2,
+							region.extents.y2,
+							scrn->bitsPerPixel,
+							kgem_choose_tiling(&sna->kgem,
+									   I915_TILING_X,
+									   region.extents.x2,
+									   region.extents.y2,
+									   sna->scrn->bitsPerPixel),
+							CREATE_SCANOUT);
+				if (shadow == NULL) {
+					DBG(("%s: failed to allocate TearFree shadow bo\n", __FUNCTION__));
+					sna_crtc->fallback_shadow = true;
+					goto force_shadow;
+				}
+
+				if (!get_fb(sna, shadow,
+					    region.extents.x2,
+					    region.extents.y2)) {
+					DBG(("%s: failed to bind fb for TearFeee shadow\n", __FUNCTION__));
+					kgem_bo_destroy(&sna->kgem, shadow);
+					sna_crtc->fallback_shadow = true;
+					goto force_shadow;
+				}
+
+				assert(__sna_pixmap_get_bo(sna->front) == NULL ||
+				       __sna_pixmap_get_bo(sna->front)->pitch == shadow->pitch);
+				sna->mode.shadow = shadow;
+				sna->mode.shadow->active_scanout++;
+			}
+			set_shadow(sna, &region);
+
+			sna_crtc_disable_override(sna, sna_crtc);
+		} else
+			sna_crtc_disable_shadow(sna, sna_crtc);
+
+		sna_crtc->rotation = rotation_reduce(&sna_crtc->primary, crtc->rotation);
+		assert(sna_crtc->primary.rotation.supported & sna_crtc->rotation);
+		return kgem_bo_reference(bo);
+	}
+}
+
+#define SCALING_EPSILON (1./256)
+
+static bool
+is_affine(const struct pixman_f_transform *t)
+{
+	return (fabs(t->m[2][0]) < SCALING_EPSILON &&
+		fabs(t->m[2][1]) < SCALING_EPSILON);
+}
+
+static double determinant(const struct pixman_f_transform *t)
+{
+	return t->m[0][0]*t->m[1][1] - t->m[1][0]*t->m[0][1];
+}
+
+static bool
+affine_is_pixel_exact(const struct pixman_f_transform *t)
+{
+	double det = t->m[2][2] * determinant(t);
+	if (fabs (det * det - 1.0) < SCALING_EPSILON) {
+		if (fabs(t->m[0][1]) < SCALING_EPSILON &&
+		    fabs(t->m[1][0]) < SCALING_EPSILON)
+			return true;
+
+		if (fabs(t->m[0][0]) < SCALING_EPSILON &&
+		    fabs(t->m[1][1]) < SCALING_EPSILON)
+			return true;
+	}
+
+	return false;
+}
+
+static void sna_crtc_randr(xf86CrtcPtr crtc)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
+	PictTransform crtc_to_fb;
+	PictFilterPtr filter;
+	xFixed *params;
+	int nparams;
+	RRTransformPtr transform;
+	int needs_transform;
+
+	transform = NULL;
+	if (crtc->transformPresent)
+		transform = &crtc->transform;
+
+	needs_transform =
+		RRTransformCompute(crtc->x, crtc->y,
+				   crtc->mode.HDisplay, crtc->mode.VDisplay,
+				   crtc->rotation, transform,
+				   &crtc_to_fb,
+				   &f_crtc_to_fb,
+				   &f_fb_to_crtc);
+
+	filter = NULL;
+	params = NULL;
+	nparams = 0;
+	if (sna_crtc->transform) {
+#ifdef RANDR_12_INTERFACE
+		if (transform) {
+			if (transform->nparams) {
+				params = malloc(transform->nparams * sizeof(xFixed));
+				if (params) {
+					memcpy(params, transform->params,
+					       transform->nparams * sizeof(xFixed));
+					nparams = transform->nparams;
+					filter = transform->filter;
+				}
+			} else
+				filter = transform->filter;
+		}
+#endif
+		crtc->transform_in_use = needs_transform;
+	} else
+		crtc->transform_in_use = sna_crtc->rotation != RR_Rotate_0;
+
+	/* Recompute the cursor after a potential change in transform */
+	if (sna_crtc->cursor) {
+		assert(sna_crtc->cursor->ref > 0);
+		sna_crtc->cursor->ref--;
+		sna_crtc->cursor = NULL;
+	}
+
+	if (needs_transform) {
+		sna_crtc->hwcursor = is_affine(&f_fb_to_crtc);
+		sna_crtc->cursor_transform =
+			sna_crtc->hwcursor &&
+			!affine_is_pixel_exact(&f_fb_to_crtc);
+	} else {
+		sna_crtc->hwcursor = true;
+		sna_crtc->cursor_transform = false;
+	}
+	DBG(("%s: hwcursor?=%d, cursor_transform?=%d\n",
+	     __FUNCTION__, sna_crtc->hwcursor, sna_crtc->cursor_transform));
+
+	crtc->crtc_to_framebuffer = crtc_to_fb;
+	crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
+	crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
+
+	free(crtc->params);
+	crtc->params  = params;
+	crtc->nparams = nparams;
+
+	crtc->filter = filter;
+	if (filter) {
+		crtc->filter_width  = filter->width;
+		crtc->filter_height = filter->height;
+	} else {
+		crtc->filter_width  = 0;
+		crtc->filter_height = 0;
+	}
+
+	crtc->bounds.x1 = 0;
+	crtc->bounds.x2 = crtc->mode.HDisplay;
+	crtc->bounds.y1 = 0;
+	crtc->bounds.y2 = crtc->mode.VDisplay;
+	pixman_f_transform_bounds(&f_crtc_to_fb, &crtc->bounds);
+
+	DBG(("%s: transform? %d, bounds (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, crtc->transform_in_use,
+	     crtc->bounds.x1, crtc->bounds.y1,
+	     crtc->bounds.x2, crtc->bounds.y2));
+}
+
+static void
+sna_crtc_damage(xf86CrtcPtr crtc)
+{
+	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
+	struct sna *sna = to_sna(crtc->scrn);
+	RegionRec region, *damage;
+
+	region.extents = crtc->bounds;
+	region.data = NULL;
+
+	if (region.extents.x1 < 0)
+		region.extents.x1 = 0;
+	if (region.extents.y1 < 0)
+		region.extents.y1 = 0;
+	if (region.extents.x2 > screen->width)
+		region.extents.x2 = screen->width;
+	if (region.extents.y2 > screen->height)
+		region.extents.y2 = screen->height;
+
+	if (region.extents.x2 <= region.extents.x1 ||
+	    region.extents.y2 <= region.extents.y1) {
+		DBG(("%s: crtc not damaged, all-clipped\n", __FUNCTION__));
+		return;
+	}
+
+	DBG(("%s: marking crtc %d as completely damaged (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, sna_crtc_id(crtc),
+	     region.extents.x1, region.extents.y1,
+	     region.extents.x2, region.extents.y2));
+
+	assert(sna->mode.shadow_damage && sna->mode.shadow_active);
+	damage = DamageRegion(sna->mode.shadow_damage);
+	RegionUnion(damage, damage, &region);
+	to_sna_crtc(crtc)->crtc_damage = region;
+
+	DBG(("%s: damage now %dx[(%d, %d), (%d, %d)]\n",
+	     __FUNCTION__,
+	     region_num_rects(damage),
+	     damage->extents.x1, damage->extents.y1,
+	     damage->extents.x2, damage->extents.y2));
+}
+
+static char *outputs_for_crtc(xf86CrtcPtr crtc, char *outputs, int max)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	int len, i;
+
+	for (i = len = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+
+		if (output->crtc != crtc)
+			continue;
+
+		len += snprintf(outputs+len, max-len, "%s, ", output->name);
+	}
+	assert(len >= 2);
+	outputs[len-2] = '\0';
+
+	return outputs;
+}
+
+static const char *rotation_to_str(Rotation rotation)
+{
+	switch (rotation & RR_Rotate_All) {
+	case 0:
+	case RR_Rotate_0: return "normal";
+	case RR_Rotate_90: return "left";
+	case RR_Rotate_180: return "inverted";
+	case RR_Rotate_270: return "right";
+	default: return "unknown";
+	}
+}
+
+static const char *reflection_to_str(Rotation rotation)
+{
+	switch (rotation & RR_Reflect_All) {
+	case 0: return "none";
+	case RR_Reflect_X: return "X axis";
+	case RR_Reflect_Y: return "Y axis";
+	case RR_Reflect_X | RR_Reflect_Y: return "X and Y axes";
+	default: return "invalid";
+	}
+}
+
+static void reprobe_connectors(xf86CrtcPtr crtc)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	struct sna *sna = to_sna(crtc->scrn);
+	int i;
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		if (output->crtc == crtc)
+			to_sna_output(output)->reprobe = true;
+	}
+
+	sna_mode_discover(sna, true);
+}
+
+static Bool
+__sna_crtc_set_mode(xf86CrtcPtr crtc)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct kgem_bo *saved_bo, *bo;
+	uint32_t saved_offset;
+	bool saved_transform;
+	bool saved_hwcursor;
+	bool saved_cursor_transform;
+	int ret;
+
+	DBG(("%s: CRTC=%d, pipe=%d, hidden?=%d\n", __FUNCTION__,
+	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), sna->mode.hidden));
+	if (sna->mode.hidden)
+		return TRUE;
+
+	saved_bo = sna_crtc->bo;
+	saved_transform = sna_crtc->transform;
+	saved_cursor_transform = sna_crtc->cursor_transform;
+	saved_hwcursor = sna_crtc->hwcursor;
+	saved_offset = sna_crtc->offset;
+
+	sna_crtc->fallback_shadow = false;
+retry: /* Attach per-crtc pixmap or direct */
+	bo = sna_crtc_attach(crtc);
+	if (bo == NULL) {
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+			   "unable to attach scanout\n");
+		goto error;
+	}
+
+	/* Prevent recursion when enabling outputs during execbuffer */
+	if (bo->exec && RQ(bo->rq)->bo == NULL) {
+		_kgem_submit(&sna->kgem);
+		__kgem_bo_clear_dirty(bo);
+	}
+
+	sna_crtc->bo = bo;
+	ret = sna_crtc_apply(crtc);
+	if (ret) {
+		kgem_bo_destroy(&sna->kgem, bo);
+
+		if (!sna_crtc->fallback_shadow) {
+			sna_crtc->fallback_shadow = true;
+			goto retry;
+		}
+
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+			   "failed to set mode: %s [%d]\n", strerror(ret), ret);
+		goto error;
+	}
+
+	sna_crtc->public.flags |= CRTC_ON;
+	bo->active_scanout++;
+	DBG(("%s: marking handle=%d as active=%d (removing %d from scanout, active=%d)\n",
+	     __FUNCTION__, bo->handle, bo->active_scanout,
+	     saved_bo ? saved_bo->handle : 0, saved_bo ? saved_bo->active_scanout - 1: -1));
+	if (saved_bo) {
+		assert(saved_bo->active_scanout);
+		assert(saved_bo->refcnt >= saved_bo->active_scanout);
+		saved_bo->active_scanout--;
+		kgem_bo_destroy(&sna->kgem, saved_bo);
+	}
+
+	sna_crtc_randr(crtc);
+	if (sna_crtc->transform)
+		sna_crtc_damage(crtc);
+	if (sna_crtc->cursor &&  /* Reload cursor if RandR maybe changed */
+	    (!sna_crtc->hwcursor ||
+	     saved_cursor_transform || sna_crtc->cursor_transform ||
+	     sna_crtc->cursor->rotation != crtc->rotation))
+		sna_crtc_disable_cursor(sna, sna_crtc);
+
+	assert(!sna->mode.hidden);
+	sna->mode.front_active += saved_bo == NULL;
+	sna->mode.dirty = true;
+	DBG(("%s: handle=%d, scanout_active=%d, front_active=%d\n",
+	     __FUNCTION__, bo->handle, bo->active_scanout, sna->mode.front_active));
+
+	return TRUE;
+
+error:
+	sna_crtc->offset = saved_offset;
+	if (sna_crtc->transform) {
+		assert(sna->mode.rr_active);
+		sna->mode.rr_active--;
+	}
+	if (saved_transform)
+		sna->mode.rr_active++;
+	sna_crtc->transform = saved_transform;
+	sna_crtc->cursor_transform = saved_cursor_transform;
+	sna_crtc->hwcursor = saved_hwcursor;
+	sna_crtc->bo = saved_bo;
+
+	reprobe_connectors(crtc);
+	return FALSE;
+}
+
+static Bool
+sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+			Rotation rotation, int x, int y)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct drm_mode_modeinfo saved_kmode;
+	char outputs[256];
+
+	if (mode->HDisplay == 0 || mode->VDisplay == 0)
+		return FALSE;
+
+	assert(sna_crtc);
+
+	xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
+		   "switch to mode %dx%d@%.1f on %s using pipe %d, position (%d, %d), rotation %s, reflection %s\n",
+		   mode->HDisplay, mode->VDisplay, xf86ModeVRefresh(mode),
+		   outputs_for_crtc(crtc, outputs, sizeof(outputs)), __sna_crtc_pipe(sna_crtc),
+		   x, y, rotation_to_str(rotation), reflection_to_str(rotation));
+
+	assert(mode->HDisplay <= sna->mode.max_crtc_width &&
+	       mode->VDisplay <= sna->mode.max_crtc_height);
+
+#if HAS_GAMMA
+	sna_crtc_gamma_set(crtc,
+			   crtc->gamma_red, crtc->gamma_green,
+			   crtc->gamma_blue, crtc->gamma_size);
+#endif
+
+	saved_kmode = sna_crtc->kmode;
+	mode_to_kmode(&sna_crtc->kmode, mode);
+	if (__sna_crtc_set_mode(crtc))
+		return TRUE;
+
+	sna_crtc->kmode = saved_kmode;
+	return FALSE;
+}
+
+static void
+sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+	DBG(("%s(pipe %d, dpms mode -> %d):= active=%d\n",
+	     __FUNCTION__, sna_crtc_pipe(crtc), mode, mode == DPMSModeOn));
+
+	if (mode == DPMSModeOn && crtc->enabled) {
+		if (__sna_crtc_set_mode(crtc))
+			update_flush_interval(to_sna(crtc->scrn));
+		else
+			mode = DPMSModeOff;
+	}
+
+	if (mode != DPMSModeOn)
+		sna_crtc_disable(crtc, false);
+}
+
+void sna_mode_adjust_frame(struct sna *sna, int x, int y)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	xf86CrtcPtr crtc;
+	int saved_x, saved_y;
+
+	if ((unsigned)config->compat_output >= config->num_output)
+		return;
+
+	crtc = config->output[config->compat_output]->crtc;
+	if (crtc == NULL || !crtc->enabled)
+		return;
+
+	if (crtc->x == x && crtc->y == y)
+		return;
+
+	saved_x = crtc->x;
+	saved_y = crtc->y;
+
+	crtc->x = x;
+	crtc->y = y;
+	if (to_sna_crtc(crtc) && !__sna_crtc_set_mode(crtc)) {
+		crtc->x = saved_x;
+		crtc->y = saved_y;
+	}
+}
+
+static void
+sna_crtc_gamma_set(xf86CrtcPtr crtc,
+		   CARD16 *red, CARD16 *green, CARD16 *blue, int size)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct drm_color_lut *lut = sna_crtc->gamma_lut;
+	uint32_t blob_size = size * sizeof(lut[0]);
+	uint32_t blob_id;
+	int ret, i;
+
+	DBG(("%s: gamma_size %d\n", __FUNCTION__, size));
+
+	if (!lut) {
+		assert(size == 256);
+
+		drmModeCrtcSetGamma(to_sna(crtc->scrn)->kgem.fd,
+				    sna_crtc_id(crtc),
+				    size, red, green, blue);
+		return;
+	}
+
+	assert(size == sna_crtc->gamma_lut_size);
+
+	for (i = 0; i < size; i++) {
+		lut[i].red = red[i];
+		lut[i].green = green[i];
+		lut[i].blue = blue[i];
+	}
+
+	ret = drmModeCreatePropertyBlob(sna->kgem.fd, lut, blob_size, &blob_id);
+	if (ret)
+		return;
+
+	ret = drmModeObjectSetProperty(sna->kgem.fd,
+				       sna_crtc->id, DRM_MODE_OBJECT_CRTC,
+				       sna_crtc->gamma_lut_prop,
+				       blob_id);
+
+	drmModeDestroyPropertyBlob(sna->kgem.fd, blob_id);
+}
+
+static void
+sna_crtc_destroy(xf86CrtcPtr crtc)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct plane *sprite, *sn;
+
+	if (sna_crtc == NULL)
+		return;
+
+	free(sna_crtc->gamma_lut);
+
+	list_for_each_entry_safe(sprite, sn, &sna_crtc->sprites, link)
+		free(sprite);
+
+	free(sna_crtc);
+	crtc->driver_private = NULL;
+}
+
+#if HAS_PIXMAP_SHARING
+static Bool
+sna_crtc_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr pixmap)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+
+	if (sna_crtc == NULL)
+		return FALSE;
+
+	if (pixmap == sna_crtc->slave_pixmap)
+		return TRUE;
+
+	DBG(("%s: CRTC:%d, pipe=%d setting scanout pixmap=%ld\n",
+	     __FUNCTION__, __sna_crtc_id(sna_crtc),  __sna_crtc_pipe(sna_crtc),
+	     pixmap ? pixmap->drawable.serialNumber : 0));
+
+	/* Disable first so that we can unregister the damage tracking */
+	sna_crtc_disable_shadow(to_sna(crtc->scrn), sna_crtc);
+
+	sna_crtc->slave_pixmap = pixmap;
+
+	return TRUE;
+}
+#endif
+
+static const xf86CrtcFuncsRec sna_crtc_funcs = {
+#if XF86_CRTC_VERSION >= 1
+	.dpms = sna_crtc_dpms,
+#endif
+	.set_mode_major = sna_crtc_set_mode_major,
+	.gamma_set = sna_crtc_gamma_set,
+	.destroy = sna_crtc_destroy,
+#if HAS_PIXMAP_SHARING
+	.set_scanout_pixmap = sna_crtc_set_scanout_pixmap,
+#endif
+};
+
+inline static bool prop_has_type_and_name(const struct drm_mode_get_property *prop,
+					  unsigned int type, const char *name)
+{
+	if ((prop->flags & (1 << type)) == 0)
+		return false;
+
+	if (strcmp(prop->name, name))
+		return false;
+
+	return true;
+}
+
+inline static bool prop_is_rotation(const struct drm_mode_get_property *prop)
+{
+	return prop_has_type_and_name(prop, 5, "rotation");
+}
+
+static void parse_rotation_prop(struct sna *sna, struct plane *p,
+				struct drm_mode_get_property *prop,
+				uint64_t value)
+{
+	struct drm_mode_property_enum *enums;
+	int j;
+
+	p->rotation.prop = prop->prop_id;
+	p->rotation.current = value;
+
+	DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n",
+	     __FUNCTION__, prop->prop_id, value, prop->count_enum_blobs));
+
+	enums = malloc(prop->count_enum_blobs * sizeof(struct drm_mode_property_enum));
+	if (!enums)
+		return;
+
+	prop->count_values = 0;
+	prop->enum_blob_ptr = (uintptr_t)enums;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, prop)) {
+		free(enums);
+		return;
+	}
+
+	/* XXX we assume that the mapping between kernel enum and
+	 * RandR remains fixed for our lifetimes.
+	 */
+	VG(VALGRIND_MAKE_MEM_DEFINED(enums, sizeof(*enums)*prop->count_enum_blobs));
+	for (j = 0; j < prop->count_enum_blobs; j++) {
+		DBG(("%s: rotation[%d] = %s [%lx]\n", __FUNCTION__,
+		     j, enums[j].name, (long)enums[j].value));
+		p->rotation.supported |= 1 << enums[j].value;
+	}
+
+	free(enums);
+}
+
+inline static bool prop_is_color_encoding(const struct drm_mode_get_property *prop)
+{
+	return prop_has_type_and_name(prop, 3, "COLOR_ENCODING");
+}
+
+static void parse_color_encoding_prop(struct sna *sna, struct plane *p,
+				      struct drm_mode_get_property *prop,
+				      uint64_t value)
+{
+	struct drm_mode_property_enum *enums;
+	unsigned int supported = 0;
+	int j;
+
+	DBG(("%s: found color encoding property .id=%d, value=%ld, num_enums=%d\n",
+	     __FUNCTION__, prop->prop_id, (long)value, prop->count_enum_blobs));
+
+	enums = malloc(prop->count_enum_blobs * sizeof(struct drm_mode_property_enum));
+	if (!enums)
+		return;
+
+	prop->count_values = 0;
+	prop->enum_blob_ptr = (uintptr_t)enums;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, prop)) {
+		free(enums);
+		return;
+	}
+
+	VG(VALGRIND_MAKE_MEM_DEFINED(enums, sizeof(*enums)*prop->count_enum_blobs));
+	for (j = 0; j < prop->count_enum_blobs; j++) {
+		if (!strcmp(enums[j].name, "ITU-R BT.601 YCbCr")) {
+			p->color_encoding.values[0] = enums[j].value;
+			supported |= 1 << 0;
+		} else if (!strcmp(enums[j].name, "ITU-R BT.709 YCbCr")) {
+			p->color_encoding.values[1] = enums[j].value;
+			supported |= 1 << 1;
+		}
+	}
+
+	free(enums);
+
+	if (supported == 3)
+		p->color_encoding.prop = prop->prop_id;
+}
+
+void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc,
+				    unsigned idx, int colorspace)
+{
+	struct plane *p;
+
+	assert(to_sna_crtc(crtc));
+	assert(colorspace < ARRAY_SIZE(p->color_encoding.values));
+
+	p = lookup_sprite(to_sna_crtc(crtc), idx);
+
+	if (!p->color_encoding.prop)
+		return;
+
+	drmModeObjectSetProperty(to_sna(crtc->scrn)->kgem.fd,
+				 p->id, DRM_MODE_OBJECT_PLANE,
+				 p->color_encoding.prop,
+				 p->color_encoding.values[colorspace]);
+}
+
+typedef void (*parse_prop_func)(struct sna *sna,
+				struct drm_mode_get_property *prop,
+				uint64_t value,
+				void *data);
+static void parse_props(struct sna *sna,
+		       uint32_t obj_type, uint32_t obj_id,
+		       parse_prop_func parse_prop,
+		       void *data)
+{
+#define N_STACK_PROPS 32 /* must be a multiple of 2 */
+	struct local_mode_obj_get_properties arg;
+	uint64_t stack[N_STACK_PROPS + N_STACK_PROPS/2];
+	uint64_t *values = stack;
+	uint32_t *props = (uint32_t *)(values + N_STACK_PROPS);
+	int i;
+
+	memset(&arg, 0, sizeof(struct local_mode_obj_get_properties));
+	arg.obj_id = obj_id;
+	arg.obj_type = obj_type;
+
+	arg.props_ptr = (uintptr_t)props;
+	arg.prop_values_ptr = (uintptr_t)values;
+	arg.count_props = N_STACK_PROPS;
+
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &arg))
+		return;
+
+	DBG(("%s: object %d (type %x) has %d props\n", __FUNCTION__,
+	     obj_id, obj_type, arg.count_props));
+
+	if (arg.count_props > N_STACK_PROPS) {
+		values = malloc(2*sizeof(uint64_t)*arg.count_props);
+		if (values == NULL)
+			return;
+
+		props = (uint32_t *)(values + arg.count_props);
+
+		arg.props_ptr = (uintptr_t)props;
+		arg.prop_values_ptr = (uintptr_t)values;
+
+		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &arg))
+			arg.count_props = 0;
+	}
+	VG(VALGRIND_MAKE_MEM_DEFINED(arg.props_ptr, sizeof(uint32_t)*arg.count_props));
+	VG(VALGRIND_MAKE_MEM_DEFINED(arg.prop_values_ptr, sizeof(uint64_t)*arg.count_props));
+
+	for (i = 0; i < arg.count_props; i++) {
+		struct drm_mode_get_property prop;
+
+		memset(&prop, 0, sizeof(prop));
+		prop.prop_id = props[i];
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
+			ERR(("%s: prop[%d].id=%d GETPROPERTY failed with errno=%d\n",
+			     __FUNCTION__, i, props[i], errno));
+			continue;
+		}
+
+		DBG(("%s: prop[%d] .id=%ld, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i,
+		     (long)props[i], prop.name, (unsigned)prop.flags, (long)values[i]));
+
+		parse_prop(sna, &prop, values[i], data);
+	}
+
+	if (values != stack)
+		free(values);
+
+#undef N_STACK_PROPS
+}
+
+static bool prop_is_type(const struct drm_mode_get_property *prop)
+{
+	return prop_has_type_and_name(prop, 3, "type");
+}
+
+static void plane_parse_prop(struct sna *sna,
+			     struct drm_mode_get_property *prop,
+			     uint64_t value, void *data)
+{
+	struct plane *p = data;
+
+	if (prop_is_type(prop))
+		p->type = value;
+	else if (prop_is_rotation(prop))
+		parse_rotation_prop(sna, p, prop, value);
+	else if (prop_is_color_encoding(prop))
+		parse_color_encoding_prop(sna, p, prop, value);
+}
+
+static int plane_details(struct sna *sna, struct plane *p)
+{
+	parse_props(sna, LOCAL_MODE_OBJECT_PLANE, p->id,
+		    plane_parse_prop, p);
+
+	p->rotation.supported &= DBG_NATIVE_ROTATION;
+	if (!xf86ReturnOptValBool(sna->Options, OPTION_ROTATION, TRUE))
+		p->rotation.supported = RR_Rotate_0;
+
+	DBG(("%s: plane=%d type=%d\n", __FUNCTION__, p->id, p->type));
+
+	return p->type;
+}
+
+static void add_sprite_plane(struct sna_crtc *crtc,
+			     struct plane *details)
+{
+	struct plane *sprite = malloc(sizeof(*sprite));
+	if (!sprite)
+		return;
+
+	memcpy(sprite, details, sizeof(*sprite));
+	list_add_tail(&sprite->link, &crtc->sprites);
+}
+
+static void
+sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
+{
+#define LOCAL_IOCTL_SET_CAP	DRM_IOWR(0x0d, struct local_set_cap)
+	struct local_set_cap {
+		uint64_t name;
+		uint64_t value;
+	} cap;
+	struct local_mode_get_plane_res r;
+	uint32_t stack_planes[32];
+	uint32_t *planes = stack_planes;
+	int i;
+
+	VG_CLEAR(cap);
+	cap.name = DRM_CLIENT_CAP_UNIVERSAL_PLANES;
+	cap.value = 1;
+	(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_SET_CAP, &cap);
+
+	VG_CLEAR(r);
+	r.plane_id_ptr = (uintptr_t)planes;
+	r.count_planes = ARRAY_SIZE(stack_planes);
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANERESOURCES, &r)) {
+		ERR(("%s: GETPLANERESOURCES failed with errno=%d\n", __FUNCTION__, errno));
+		return;
+	}
+
+	DBG(("%s: %d planes\n", __FUNCTION__, (int)r.count_planes));
+
+	if (r.count_planes > ARRAY_SIZE(stack_planes)) {
+		planes = malloc(sizeof(uint32_t)*r.count_planes);
+		if (planes == NULL)
+			return;
+
+		r.plane_id_ptr = (uintptr_t)planes;
+		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANERESOURCES, &r))
+			r.count_planes = 0;
+	}
+
+	VG(VALGRIND_MAKE_MEM_DEFINED(planes, sizeof(uint32_t)*r.count_planes));
+
+	for (i = 0; i < r.count_planes; i++) {
+		struct local_mode_get_plane p;
+		struct plane details;
+
+		VG_CLEAR(p);
+		p.plane_id = planes[i];
+		p.count_format_types = 0;
+		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANE, &p))
+			continue;
+
+		if ((p.possible_crtcs & (1 << __sna_crtc_pipe(crtc))) == 0)
+			continue;
+
+		DBG(("%s: plane %d is attached to our pipe=%d\n",
+		     __FUNCTION__, planes[i], __sna_crtc_pipe(crtc)));
+
+		details.id = p.plane_id;
+		details.rotation.prop = 0;
+		details.rotation.supported = RR_Rotate_0;
+		details.rotation.current = RR_Rotate_0;
+
+		switch (plane_details(sna, &details)) {
+		default:
+			break;
+
+		case DRM_PLANE_TYPE_PRIMARY:
+			crtc->primary = details;
+			break;
+
+		case DRM_PLANE_TYPE_CURSOR:
+			break;
+
+		case DRM_PLANE_TYPE_OVERLAY:
+			add_sprite_plane(crtc, &details);
+			break;
+		}
+	}
+
+	if (planes != stack_planes)
+		free(planes);
+}
+
+static bool plane_has_format(const uint32_t formats[],
+			     int count_formats,
+			     uint32_t format)
+{
+	int i;
+
+	for (i = 0; i < count_formats; i++) {
+		if (formats[i] == format)
+			return true;
+	}
+
+	return false;
+}
+
+bool sna_has_sprite_format(struct sna *sna, uint32_t format)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	if (sna->mode.num_real_crtc == 0)
+		return false;
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *sna_crtc = to_sna_crtc(config->crtc[i]);
+		struct plane *plane;
+
+		list_for_each_entry(plane, &sna_crtc->sprites, link) {
+			struct local_mode_get_plane p;
+			uint32_t *formats;
+			int count_formats;
+			bool has_format;
+
+			VG_CLEAR(p);
+			p.plane_id = plane->id;
+			p.count_format_types = 0;
+			if (drmIoctl(sna->kgem.fd,
+				     LOCAL_IOCTL_MODE_GETPLANE,
+				     &p))
+				continue;
+			count_formats = p.count_format_types;
+
+			formats = calloc(count_formats, sizeof(formats[0]));
+			if (!formats)
+				continue;
+
+			p.count_format_types = count_formats;
+			p.format_type_ptr = (uintptr_t)formats;
+			if (drmIoctl(sna->kgem.fd,
+				     LOCAL_IOCTL_MODE_GETPLANE,
+				     &p)) {
+				free(formats);
+				continue;
+			}
+
+			assert(p.count_format_types == count_formats);
+
+			has_format = plane_has_format(formats,
+						      count_formats,
+						      format);
+
+			free(formats);
+
+			/*
+			 * As long as one plane supports the
+			 * format we declare it as supported.
+			 * Not all planes may support it, but
+			 * then the GPU fallback will kick in.
+			 */
+			if (has_format)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+inline static bool prop_is_gamma_lut(const struct drm_mode_get_property *prop)
+{
+	return prop_has_type_and_name(prop, 4, "GAMMA_LUT");
+}
+
+inline static bool prop_is_gamma_lut_size(const struct drm_mode_get_property *prop)
+{
+	return prop_has_type_and_name(prop, 1, "GAMMA_LUT_SIZE");
+}
+
+static void sna_crtc_parse_prop(struct sna *sna,
+				struct drm_mode_get_property *prop,
+				uint64_t value, void *data)
+{
+	struct sna_crtc *crtc = data;
+
+	if (prop_is_gamma_lut(prop)) {
+		crtc->gamma_lut_prop = prop->prop_id;
+		crtc->gamma_lut_blob = value;
+	} else if (prop_is_gamma_lut_size(prop)) {
+		crtc->gamma_lut_size = value;
+	}
+}
+
+static void
+sna_crtc_init__props(struct sna *sna, struct sna_crtc *crtc)
+{
+	ScrnInfoPtr scrn = sna->scrn;
+
+	parse_props(sna, LOCAL_MODE_OBJECT_CRTC, crtc->id,
+		    sna_crtc_parse_prop, crtc);
+
+	/* use high precision gamma LUT for > 8bpc */
+	/* X-Server < 1.20 mishandles > 256 slots / > 8 bpc color maps. */
+	if (scrn->rgbBits <= 8 ||
+	    XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,0,0,0))
+		crtc->gamma_lut_size = 0;
+
+	if (crtc->gamma_lut_size) {
+		crtc->gamma_lut = calloc(max(crtc->gamma_lut_size, 256),
+					 sizeof(crtc->gamma_lut[0]));
+		if (!crtc->gamma_lut)
+			crtc->gamma_lut_size = 0;
+	}
+
+	DBG(("%s: CRTC:%d, gamma_lut_size=%d\n", __FUNCTION__,
+	     __sna_crtc_id(crtc), crtc->gamma_lut_size));
+}
+
+static void
+sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *crtc)
+{
+	crtc->rotation = RR_Rotate_0;
+	crtc->primary.rotation.supported = RR_Rotate_0;
+	crtc->primary.rotation.current = RR_Rotate_0;
+}
+
+static void
+sna_crtc_init__cursor(struct sna *sna, struct sna_crtc *crtc)
+{
+	struct drm_mode_cursor arg;
+
+	VG_CLEAR(arg);
+	arg.flags = DRM_MODE_CURSOR_BO;
+	arg.crtc_id = __sna_crtc_id(crtc);
+	arg.width = arg.height = 0;
+	arg.handle = 0;
+
+	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
+	crtc->hwcursor = true;
+}
+
+static bool
+sna_crtc_add(ScrnInfoPtr scrn, unsigned id)
+{
+	struct sna *sna = to_sna(scrn);
+	xf86CrtcPtr crtc;
+	struct sna_crtc *sna_crtc;
+	struct drm_i915_get_pipe_from_crtc_id get_pipe;
+
+	DBG(("%s(%d): is-zaphod? %d\n", __FUNCTION__, id, is_zaphod(scrn)));
+
+	sna_crtc = calloc(sizeof(struct sna_crtc), 1);
+	if (sna_crtc == NULL)
+		return false;
+
+	list_init(&sna_crtc->public.vblank_queue);
+	sna_crtc->id = id;
+
+	VG_CLEAR(get_pipe);
+	get_pipe.pipe = 0;
+	get_pipe.crtc_id = id;
+	if (drmIoctl(sna->kgem.fd,
+		     DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
+		     &get_pipe)) {
+		free(sna_crtc);
+		return false;
+	}
+	assert((unsigned)get_pipe.pipe < 256);
+	sna_crtc->public.flags |= get_pipe.pipe << 8;
+
+	if (is_zaphod(scrn) &&
+	    (get_zaphod_crtcs(sna) & (1 << get_pipe.pipe)) == 0) {
+		free(sna_crtc);
+		return true;
+	}
+
+	list_init(&sna_crtc->sprites);
+	sna_crtc_init__rotation(sna, sna_crtc);
+
+	sna_crtc_init__props(sna, sna_crtc);
+
+	sna_crtc_find_planes(sna, sna_crtc);
+
+	DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, current-rotation=%x\n",
+	     __FUNCTION__, id, get_pipe.pipe,
+	     sna_crtc->primary.id, sna_crtc->primary.rotation.supported, sna_crtc->primary.rotation.current));
+
+	list_init(&sna_crtc->shadow_link);
+
+	crtc = xf86CrtcCreate(scrn, &sna_crtc_funcs);
+	if (crtc == NULL) {
+		free(sna_crtc);
+		return false;
+	}
+
+	sna_crtc_init__cursor(sna, sna_crtc);
+
+	crtc->driver_private = sna_crtc;
+	sna_crtc->base = crtc;
+	DBG(("%s: attached crtc[%d] pipe=%d\n",
+	     __FUNCTION__, id, __sna_crtc_pipe(sna_crtc)));
+
+	return true;
+}
+
+static bool
+is_panel(int type)
+{
+#define DRM_MODE_CONNECTOR_LVDS 7
+#define DRM_MODE_CONNECTOR_eDP 14
+#define DRM_MODE_CONNECTOR_DSI 16
+	return (type == DRM_MODE_CONNECTOR_LVDS ||
+		type == DRM_MODE_CONNECTOR_eDP ||
+		type == DRM_MODE_CONNECTOR_DSI);
+}
+
+static int
+find_property(struct sna *sna, struct sna_output *output, const char *name)
+{
+	struct drm_mode_get_property prop;
+	int i;
+
+	VG_CLEAR(prop);
+	for (i = 0; i < output->num_props; i++) {
+		prop.prop_id = output->prop_ids[i];
+		prop.count_values = 0;
+		prop.count_enum_blobs = 0;
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
+			continue;
+
+		if (strcmp(prop.name, name) == 0)
+			return i;
+	}
+
+	return -1;
+}
+
+static void update_properties(struct sna *sna, struct sna_output *output)
+{
+	union compat_mode_get_connector compat_conn;
+	struct drm_mode_modeinfo dummy;
+
+	VG_CLEAR(compat_conn);
+
+	compat_conn.conn.connector_id = output->id;
+	compat_conn.conn.count_props = output->num_props;
+	compat_conn.conn.props_ptr = (uintptr_t)output->prop_ids;
+	compat_conn.conn.prop_values_ptr = (uintptr_t)output->prop_values;
+	compat_conn.conn.count_modes = 1; /* skip detect */
+	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
+	compat_conn.conn.count_encoders = 0;
+
+	(void)drmIoctl(sna->kgem.fd,
+		       DRM_IOCTL_MODE_GETCONNECTOR,
+		       &compat_conn.conn);
+
+	assert(compat_conn.conn.count_props == output->num_props);
+	output->update_properties = false;
+}
+
+static xf86OutputStatus
+sna_output_detect(xf86OutputPtr output)
+{
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	union compat_mode_get_connector compat_conn;
+	uint32_t now;
+
+	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
+	sna_output->update_properties = false;
+
+	if (!sna_output->id) {
+		DBG(("%s(%s) hiding due to lost connection\n", __FUNCTION__, output->name));
+		return XF86OutputStatusDisconnected;
+	}
+
+	/* Cache detections for 15s or hotplug event  */
+	now = GetTimeInMillis();
+	if (sna_output->last_detect != 0 &&
+	    (int32_t)(now - sna_output->last_detect) <= OUTPUT_STATUS_CACHE_MS) {
+		DBG(("%s(%s) reporting cached status (since %dms): %d\n",
+		     __FUNCTION__, output->name, now - sna_output->last_detect,
+		     sna_output->status));
+		sna_output->update_properties = true;
+		return sna_output->status;
+	}
+
+	VG_CLEAR(compat_conn);
+	compat_conn.conn.connector_id = sna_output->id;
+	sna_output->num_modes = compat_conn.conn.count_modes = 0; /* reprobe */
+	compat_conn.conn.count_encoders = 0;
+	compat_conn.conn.count_props = sna_output->num_props;
+	compat_conn.conn.props_ptr = (uintptr_t)sna_output->prop_ids;
+	compat_conn.conn.prop_values_ptr = (uintptr_t)sna_output->prop_values;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &compat_conn.conn))
+		return XF86OutputStatusUnknown;
+	DBG(("%s(%s): num modes %d -> %d, num props %d -> %d\n",
+	     __FUNCTION__, output->name,
+	     sna_output->num_modes, compat_conn.conn.count_modes,
+	     sna_output->num_props, compat_conn.conn.count_props));
+
+	assert(compat_conn.conn.count_props == sna_output->num_props);
+
+	while (compat_conn.conn.count_modes && compat_conn.conn.count_modes != sna_output->num_modes) {
+		struct drm_mode_modeinfo *new_modes;
+		int old_count;
+
+		old_count = sna_output->num_modes;
+		new_modes = realloc(sna_output->modes,
+				    sizeof(*sna_output->modes)*compat_conn.conn.count_modes);
+		if (new_modes == NULL)
+			break;
+
+		sna_output->modes = new_modes;
+		sna_output->num_modes = compat_conn.conn.count_modes;
+		compat_conn.conn.modes_ptr = (uintptr_t)sna_output->modes;
+		compat_conn.conn.count_encoders = 0;
+		compat_conn.conn.count_props = 0;
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &compat_conn.conn)) {
+			sna_output->num_modes = min(old_count, sna_output->num_modes);
+			break;
+		}
+		VG(VALGRIND_MAKE_MEM_DEFINED(sna_output->modes, sizeof(*sna_output->modes)*sna_output->num_modes));
+	}
+
+	DBG(("%s(%s): found %d modes, connection status=%d\n",
+	     __FUNCTION__, output->name, sna_output->num_modes, compat_conn.conn.connection));
+
+	sna_output->reprobe = false;
+	sna_output->last_detect = now;
+	switch (compat_conn.conn.connection) {
+	case DRM_MODE_CONNECTED:
+		sna_output->status = XF86OutputStatusConnected;
+		output->mm_width = compat_conn.conn.mm_width;
+		output->mm_height = compat_conn.conn.mm_height;
+		break;
+	case DRM_MODE_DISCONNECTED:
+		sna_output->status = XF86OutputStatusDisconnected;
+		break;
+	default:
+	case DRM_MODE_UNKNOWNCONNECTION:
+		sna_output->status = XF86OutputStatusUnknown;
+		break;
+	}
+	return sna_output->status;
+}
+
+static Bool
+sna_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
+{
+	struct sna_output *sna_output = output->driver_private;
+	struct sna *sna = to_sna(output->scrn);
+
+	if (mode->HDisplay > sna->mode.max_crtc_width)
+		return MODE_VIRTUAL_X;
+	if (mode->VDisplay > sna->mode.max_crtc_height)
+		return MODE_VIRTUAL_Y;
+
+	/* Check that we can successfully pin this into the global GTT */
+	if ((kgem_can_create_2d(&sna->kgem,
+				mode->HDisplay, mode->VDisplay,
+				sna->scrn->bitsPerPixel) & KGEM_CAN_CREATE_GTT) == 0)
+		return MODE_MEM_VIRT;
+
+	/*
+	 * If the connector type is a panel, we will use the panel limit to
+	 * verfiy whether the mode is valid.
+	 */
+	if (sna_output->has_panel_limits) {
+		if (mode->HDisplay > sna_output->panel_hdisplay ||
+		    mode->VDisplay > sna_output->panel_vdisplay)
+			return MODE_PANEL;
+	}
+
+	return MODE_OK;
+}
+
+static void sna_output_set_parsed_edid(xf86OutputPtr output, xf86MonPtr mon)
+{
+	unsigned conn_mm_width, conn_mm_height;
+
+	/* We set the output size based on values from the kernel */
+	conn_mm_width = output->mm_width;
+	conn_mm_height = output->mm_height;
+
+	xf86OutputSetEDID(output, mon);
+
+	if (output->mm_width != conn_mm_width || output->mm_height != conn_mm_height) {
+		DBG(("%s)%s): kernel and Xorg disagree over physical size: kernel=%dx%dmm, Xorg=%dx%dmm\n",
+		     __FUNCTION__, output->name,
+		     conn_mm_width, conn_mm_height,
+		     output->mm_width, output->mm_height));
+	}
+
+	output->mm_width = conn_mm_width;
+	output->mm_height = conn_mm_height;
+}
+
+static void
+sna_output_attach_edid(xf86OutputPtr output)
+{
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	unsigned old_mm_width, old_mm_height;
+	struct drm_mode_get_blob blob;
+	void *old, *raw = NULL;
+	xf86MonPtr mon = NULL;
+
+	if (sna_output->edid_idx == -1)
+		return;
+
+	/* Always refresh the blob as the kernel may randomly update the
+	 * id even if the contents of the blob doesn't change, and a
+	 * request for the stale id will return nothing.
+	 */
+	if (sna_output->update_properties)
+		update_properties(sna, sna_output);
+
+	raw = sna_output->edid_raw;
+	blob.length = sna_output->edid_len;
+
+	if (blob.length && output->MonInfo) {
+		old = alloca(blob.length);
+		memcpy(old, raw, blob.length);
+	} else
+		old = NULL;
+
+	blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
+	if (!blob.blob_id)
+		goto done;
+
+	DBG(("%s(%s): attaching EDID id=%d, current=%d\n",
+	     __FUNCTION__, output->name,
+	     blob.blob_id, sna_output->edid_blob_id));
+	if (blob.blob_id == sna_output->edid_blob_id && 0) { /* sigh */
+		if (output->MonInfo) {
+			/* XXX the property keeps on disappearing... */
+			RRChangeOutputProperty(output->randr_output,
+					       MakeAtom("EDID", strlen("EDID"), TRUE),
+					       XA_INTEGER, 8, PropModeReplace,
+					       sna_output->edid_len,
+					       sna_output->edid_raw,
+					       FALSE, FALSE);
+
+			return;
+		}
+
+		goto skip_read;
+	}
+
+	blob.data = (uintptr_t)raw;
+	do {
+		while (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
+			update_properties(sna, sna_output);
+			if (blob.blob_id == sna_output->prop_values[sna_output->edid_idx]) {
+				DBG(("%s(%s): failed to read blob, reusing previous\n",
+				     __FUNCTION__, output->name));
+				goto done;
+			}
+			blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
+		}
+
+		DBG(("%s(%s): retrieving blob id=%d, length=%d\n",
+		     __FUNCTION__, output->name, blob.blob_id, blob.length));
+
+		if (blob.length < 128)
+			goto done;
+
+		if (blob.length > sna_output->edid_len) {
+			raw = realloc(raw, blob.length);
+			if (raw == NULL)
+				goto done;
+
+			VG(memset(raw, 0, blob.length));
+			blob.data = (uintptr_t)raw;
+		}
+	} while (blob.length != sna_output->edid_len &&
+		 drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob));
+
+	if (blob.length & 127) {
+		/* Truncated EDID! Make sure no one reads too far */
+		*SECTION(NO_EDID, (uint8_t*)raw) = blob.length/128 - 1;
+		blob.length &= -128;
+	}
+
+	if (old &&
+	    blob.length == sna_output->edid_len &&
+	    memcmp(old, raw, blob.length) == 0) {
+		DBG(("%s(%s): EDID + MonInfo is unchanged\n",
+		     __FUNCTION__, output->name));
+		assert(sna_output->edid_raw == raw);
+		sna_output->edid_blob_id = blob.blob_id;
+		RRChangeOutputProperty(output->randr_output,
+				       MakeAtom("EDID", strlen("EDID"), TRUE),
+				       XA_INTEGER, 8, PropModeReplace,
+				       sna_output->edid_len,
+				       sna_output->edid_raw,
+				       FALSE, FALSE);
+		return;
+	}
+
+skip_read:
+	if (raw) {
+		mon = xf86InterpretEDID(output->scrn->scrnIndex, raw);
+		if (mon && blob.length > 128)
+			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
+	}
+
+done:
+	output = sna_output->base;
+	old_mm_width = output->mm_width;
+	old_mm_height = output->mm_height;
+	sna_output_set_parsed_edid(output, mon);
+	if (raw) {
+		sna_output->edid_raw = raw;
+		sna_output->edid_len = blob.length;
+		sna_output->edid_blob_id = blob.blob_id;
+	}
+	output->mm_width = old_mm_width;
+	output->mm_height = old_mm_height;
+}
+
+static void
+sna_output_attach_tile(xf86OutputPtr output)
+{
+#if XF86_OUTPUT_VERSION >= 3
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	struct drm_mode_get_blob blob;
+	struct xf86CrtcTileInfo tile_info, *set = NULL;
+	char *tile;
+	int id;
+
+	id = find_property(sna, sna_output, "TILE");
+	DBG(("%s: found? TILE=%d\n", __FUNCTION__, id));
+	if (id == -1)
+		goto out;
+
+	if (sna_output->update_properties)
+		update_properties(sna, sna_output);
+
+	VG_CLEAR(blob);
+	blob.blob_id = sna_output->prop_values[id];
+	blob.length = 0;
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+		goto out;
+
+	do {
+		id = blob.length;
+		tile = alloca(id + 1);
+		blob.data = (uintptr_t)tile;
+		VG(memset(tile, 0, id));
+		DBG(("%s: reading %d bytes for TILE blob\n", __FUNCTION__, id));
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+			goto out;
+	} while (id != blob.length);
+
+	tile[blob.length] = '\0'; /* paranoia */
+	DBG(("%s: TILE='%s'\n", __FUNCTION__, tile));
+	if (xf86OutputParseKMSTile(tile, blob.length, &tile_info))
+		set = &tile_info;
+out:
+	xf86OutputSetTile(output, set);
+#endif
+}
+
+static bool duplicate_mode(DisplayModePtr modes, DisplayModePtr m)
+{
+	if (m == NULL)
+		return false;
+
+	while (modes) {
+		if (xf86ModesEqual(modes, m))
+			return true;
+
+		modes = modes->next;
+	}
+
+	return false;
+}
+
+static struct pixel_count {
+	int16_t width, height;
+} common_16_9[] = {
+	{ 640, 360 },
+	{ 720, 405 },
+	{ 864, 486 },
+	{ 960, 540 },
+	{ 1024, 576 },
+	{ 1280, 720 },
+	{ 1366, 768 },
+	{ 1600, 900 },
+	{ 1920, 1080 },
+	{ 2048, 1152 },
+	{ 2560, 1440 },
+	{ 2880, 1620 },
+	{ 3200, 1800 },
+	{ 3840, 2160 },
+	{ 4096, 2304 },
+	{ 5120, 2880 },
+	{ 7680, 4320 },
+	{ 15360, 8640 },
+}, common_16_10[] = {
+	{ 1280, 800 },
+	{ 1400, 900 },
+	{ 1680, 1050 },
+	{ 1920, 1200 },
+	{ 2560, 1600 },
+};
+
+static DisplayModePtr
+default_modes(DisplayModePtr preferred)
+{
+	DisplayModePtr modes;
+	int n;
+
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,900,0)
+	modes = xf86GetDefaultModes();
+#else
+	modes = xf86GetDefaultModes(0, 0);
+#endif
+
+	/* XXX O(n^2) mode list generation :( */
+
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,901,0)
+	if (preferred) {
+		DisplayModePtr m;
+
+		/* Add a half-resolution mode useful for large panels */
+		m = xf86GTFMode(preferred->HDisplay/2,
+				preferred->VDisplay/2,
+				xf86ModeVRefresh(preferred),
+				FALSE, FALSE);
+		if (!duplicate_mode(modes, m))
+			modes = xf86ModesAdd(modes, m);
+		else
+			free(m);
+
+		if (preferred->VDisplay * 16 > preferred->HDisplay*9 - preferred->HDisplay/32 &&
+		    preferred->VDisplay * 16 < preferred->HDisplay*9 + preferred->HDisplay/32) {
+			DBG(("Adding 16:9 modes -- %d < %d > %d\n",
+			     preferred->HDisplay*9 - preferred->HDisplay/32,
+			     preferred->VDisplay * 16,
+			     preferred->HDisplay*9 + preferred->HDisplay/32));
+			for (n = 0; n < ARRAY_SIZE(common_16_9); n++) {
+				if (preferred->HDisplay <= common_16_9[n].width ||
+				    preferred->VDisplay <= common_16_9[n].height)
+					break;
+
+				m = xf86GTFMode(common_16_9[n].width,
+						common_16_9[n].height,
+						xf86ModeVRefresh(preferred),
+						FALSE, FALSE);
+				if (!duplicate_mode(modes, m))
+					modes = xf86ModesAdd(modes, m);
+				else
+					free(m);
+			}
+		}
+
+		if (preferred->VDisplay * 16 > preferred->HDisplay*10 - preferred->HDisplay/32 &&
+		    preferred->VDisplay * 16 < preferred->HDisplay*10 + preferred->HDisplay/32) {
+			DBG(("Adding 16:10 modes -- %d < %d > %d\n",
+			     preferred->HDisplay*10 - preferred->HDisplay/32,
+			     preferred->VDisplay * 16,
+			     preferred->HDisplay*10 + preferred->HDisplay/32));
+			for (n = 0; n < ARRAY_SIZE(common_16_10); n++) {
+				if (preferred->HDisplay <= common_16_10[n].width ||
+				    preferred->VDisplay <= common_16_10[n].height)
+					break;
+
+				m = xf86GTFMode(common_16_10[n].width,
+						common_16_10[n].height,
+						xf86ModeVRefresh(preferred),
+						FALSE, FALSE);
+				if (!duplicate_mode(modes, m))
+					modes = xf86ModesAdd(modes, m);
+				else
+					free(m);
+			}
+		}
+	}
+#endif
+
+	return modes;
+}
+
+static DisplayModePtr
+sna_output_add_default_modes(xf86OutputPtr output, DisplayModePtr modes)
+{
+	xf86MonPtr mon = output->MonInfo;
+	DisplayModePtr i, m, preferred = NULL;
+	int max_x = 0, max_y = 0, max_clock = 0;
+	float max_vrefresh = 0.0;
+
+	if (mon && GTF_SUPPORTED(mon->features.msc))
+		return modes;
+
+	for (m = modes; m; m = m->next) {
+		if (m->type & M_T_PREFERRED)
+			preferred = m;
+		max_x = max(max_x, m->HDisplay);
+		max_y = max(max_y, m->VDisplay);
+		max_clock = max(max_clock, m->Clock);
+		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
+	}
+	max_vrefresh *= (1 + SYNC_TOLERANCE);
+
+	m = default_modes(preferred);
+	xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
+
+	for (i = m; i; i = i->next) {
+		if (i->Clock > max_clock)
+			i->status = MODE_CLOCK_HIGH;
+		if (xf86ModeVRefresh(i) > max_vrefresh)
+			i->status = MODE_VSYNC;
+		if (preferred &&
+		    i->HDisplay >= preferred->HDisplay &&
+		    i->VDisplay >= preferred->VDisplay &&
+		    xf86ModeVRefresh(i) >= xf86ModeVRefresh(preferred))
+			i->status = MODE_PANEL;
+	}
+
+	xf86PruneInvalidModes(output->scrn, &m, FALSE);
+
+	return xf86ModesAdd(modes, m);
+}
+
+static DisplayModePtr
+sna_output_override_edid(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	xf86MonPtr mon = NULL;
+
+	if (sna_output->fake_edid_raw == NULL)
+		return NULL;
+
+	mon = xf86InterpretEDID(output->scrn->scrnIndex, sna_output->fake_edid_raw);
+	if (mon == NULL) {
+		return NULL;
+	}
+
+	mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
+
+	xf86OutputSetEDID(output, mon);
+
+	return xf86DDCGetModes(output->scrn->scrnIndex, mon);
+}
+
+static DisplayModePtr
+sna_output_get_modes(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	DisplayModePtr Modes, current;
+	int i;
+
+	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
+	assert(sna_output->id);
+
+	Modes = sna_output_override_edid(output);
+	if (Modes)
+		return Modes;
+
+	sna_output_attach_edid(output);
+	sna_output_attach_tile(output);
+
+	current = NULL;
+	if (output->crtc && !sna_output->hotplug_count) {
+		struct drm_mode_crtc mode;
+
+		VG_CLEAR(mode);
+		assert(to_sna_crtc(output->crtc));
+		mode.crtc_id = sna_crtc_id(output->crtc);
+
+		if (drmIoctl(to_sna(output->scrn)->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode) == 0) {
+			DBG(("%s: CRTC:%d, pipe=%d: has mode?=%d\n", __FUNCTION__,
+			     sna_crtc_id(output->crtc),
+			     sna_crtc_pipe(output->crtc),
+			     mode.mode_valid && mode.mode.clock));
+
+			if (mode.mode_valid && mode.mode.clock) {
+				current = calloc(1, sizeof(DisplayModeRec));
+				if (current) {
+					mode_from_kmode(output->scrn, &mode.mode, current);
+					current->type |= M_T_DRIVER | M_T_PREFERRED;
+				}
+			}
+		}
+	}
+
+	DBG(("%s: adding %d probed modes\n", __FUNCTION__, sna_output->num_modes));
+
+	for (i = 0; i < sna_output->num_modes; i++) {
+		DisplayModePtr mode;
+
+		mode = calloc(1, sizeof(DisplayModeRec));
+		if (mode == NULL)
+			continue;
+
+		mode = mode_from_kmode(output->scrn,
+				       &sna_output->modes[i],
+				       mode);
+		Modes = xf86ModesAdd(Modes, mode);
+		if (current && xf86ModesEqual(mode, current)) {
+			free((void*)current->name);
+			free(current);
+			current = NULL;
+		}
+		if (current && mode->type & M_T_PREFERRED)
+			current->type &= ~M_T_PREFERRED;
+	}
+
+	if (current)
+		Modes = xf86ModesAdd(current, Modes);
+
+	/*
+	 * If the connector type is a panel, we will traverse the kernel mode to
+	 * get the panel limit. And then add all the standard modes to fake
+	 * the fullscreen experience.
+	 * If it is incorrect, please fix me.
+	 */
+	sna_output->has_panel_limits = false;
+	if (sna_output->is_panel) {
+		sna_output->panel_hdisplay = sna_output->panel_vdisplay = 0;
+		for (i = 0; i < sna_output->num_modes; i++) {
+			struct drm_mode_modeinfo *m;
+
+			m = &sna_output->modes[i];
+			if (m->hdisplay > sna_output->panel_hdisplay)
+				sna_output->panel_hdisplay = m->hdisplay;
+			if (m->vdisplay > sna_output->panel_vdisplay)
+				sna_output->panel_vdisplay = m->vdisplay;
+		}
+		sna_output->has_panel_limits =
+			sna_output->panel_hdisplay &&
+			sna_output->panel_vdisplay;
+	}
+
+	if (sna_output->add_default_modes)
+		Modes = sna_output_add_default_modes(output, Modes);
+
+	return Modes;
+}
+
+static void
+sna_output_destroy(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	int i;
+
+	if (sna_output == NULL)
+		return;
+
+	free(sna_output->edid_raw);
+	free(sna_output->fake_edid_raw);
+
+	for (i = 0; i < sna_output->num_props; i++) {
+		if (sna_output->props[i].kprop == NULL)
+			continue;
+
+		if (sna_output->props[i].atoms) {
+			if (output->randr_output)
+				RRDeleteOutputProperty(output->randr_output, sna_output->props[i].atoms[0]);
+			free(sna_output->props[i].atoms);
+		}
+
+		drmModeFreeProperty(sna_output->props[i].kprop);
+	}
+	free(sna_output->props);
+	free(sna_output->prop_ids);
+	free(sna_output->prop_values);
+
+	backlight_close(&sna_output->backlight);
+
+	free(sna_output);
+	output->driver_private = NULL;
+}
+
+static void
+__sna_output_dpms(xf86OutputPtr output, int dpms, int fixup)
+{
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	int old_dpms = sna_output->dpms_mode;
+
+	DBG(("%s(%s:%d): dpms=%d (current: %d), active? %d\n",
+	     __FUNCTION__, output->name, sna_output->id,
+	     dpms, sna_output->dpms_mode,
+	     output->crtc != NULL));
+
+	if (!sna_output->id)
+		return;
+
+	if (old_dpms == dpms)
+		return;
+
+	/* Record the value of the backlight before turning
+	 * off the display, and reset if after turning it on.
+	 * Order is important as the kernel may record and also
+	 * reset the backlight across DPMS. Hence we need to
+	 * record the value before the kernel modifies it
+	 * and reapply it afterwards.
+	 */
+	if (sna_output->backlight.iface && dpms != DPMSModeOn) {
+		if (old_dpms == DPMSModeOn) {
+			sna_output->backlight_active_level = sna_output_backlight_get(output);
+			DBG(("%s(%s:%d): saving current backlight %d\n",
+			     __FUNCTION__, output->name, sna_output->id,
+			     sna_output->backlight_active_level));
+		}
+		sna_output->dpms_mode = dpms;
+		sna_output_backlight_off(sna_output);
+	}
+
+	if (output->crtc &&
+	    drmModeConnectorSetProperty(sna->kgem.fd,
+					sna_output->id,
+					sna_output->dpms_id,
+					dpms)) {
+		DBG(("%s(%s:%d): failed to set DPMS to %d (fixup? %d)\n",
+		     __FUNCTION__, output->name, sna_output->id, dpms, fixup));
+		if (fixup && dpms != DPMSModeOn) {
+			sna_crtc_disable(output->crtc, false);
+			return;
+		}
+	}
+
+	if (sna_output->backlight.iface && dpms == DPMSModeOn) {
+		DBG(("%s(%d:%d: restoring previous backlight %d\n",
+		     __FUNCTION__, output->name, sna_output->id,
+		     sna_output->backlight_active_level));
+		sna_output_backlight_on(sna_output);
+	}
+
+	sna_output->dpms_mode = dpms;
+}
+
+static void
+sna_output_dpms(xf86OutputPtr output, int dpms)
+{
+	__sna_output_dpms(output, dpms, true);
+}
+
+static bool
+sna_property_ignore(drmModePropertyPtr prop)
+{
+	if (!prop)
+		return true;
+
+	/* ignore blob prop */
+	if (prop->flags & DRM_MODE_PROP_BLOB)
+		return true;
+
+	/* ignore standard property */
+	if (!strcmp(prop->name, "EDID") ||
+	    !strcmp(prop->name, "DPMS"))
+		return true;
+
+	return false;
+}
+
+static void
+sna_output_create_ranged_atom(xf86OutputPtr output, Atom *atom,
+			      const char *name, INT32 min, INT32 max,
+			      uint64_t value, Bool immutable)
+{
+	int err;
+	INT32 atom_range[2];
+
+	atom_range[0] = min;
+	atom_range[1] = max;
+
+	*atom = MakeAtom(name, strlen(name), TRUE);
+
+	err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE,
+					TRUE, immutable, 2, atom_range);
+	if (err != 0)
+		xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
+			   "RRConfigureOutputProperty error, %d\n", err);
+
+	err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER,
+				     32, PropModeReplace, 1, &value,
+				     FALSE, FALSE);
+	if (err != 0)
+		xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
+			   "RRChangeOutputProperty error, %d\n", err);
+}
+
+static void
+sna_output_create_resources(xf86OutputPtr output)
+{
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	int i, j, err;
+
+	sna_output->props = calloc(sna_output->num_props,
+				   sizeof(struct sna_property));
+	if (!sna_output->props)
+		return;
+
+	for (i = 0; i < sna_output->num_props; i++) {
+		struct sna_property *p = &sna_output->props[i];
+
+		p->kprop = drmModeGetProperty(sna->kgem.fd,
+					      sna_output->prop_ids[i]);
+		if (sna_property_ignore(p->kprop)) {
+			drmModeFreeProperty(p->kprop);
+			p->kprop = NULL;
+			continue;
+		}
+
+		if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
+			p->num_atoms = 1;
+			p->atoms = calloc(p->num_atoms, sizeof(Atom));
+			if (!p->atoms)
+				continue;
+
+			sna_output_create_ranged_atom(output, &p->atoms[0],
+						      p->kprop->name,
+						      p->kprop->values[0],
+						      p->kprop->values[1],
+						      sna_output->prop_values[i],
+						      p->kprop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE);
+
+		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
+			p->num_atoms = p->kprop->count_enums + 1;
+			p->atoms = calloc(p->num_atoms, sizeof(Atom));
+			if (!p->atoms)
+				continue;
+
+			p->atoms[0] = MakeAtom(p->kprop->name, strlen(p->kprop->name), TRUE);
+			for (j = 1; j <= p->kprop->count_enums; j++) {
+				struct drm_mode_property_enum *e = &p->kprop->enums[j-1];
+				p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
+			}
+
+			err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+							FALSE, FALSE,
+							p->kprop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+							p->num_atoms - 1, (INT32 *)&p->atoms[1]);
+			if (err != 0) {
+				xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
+					   "RRConfigureOutputProperty error, %d\n", err);
+			}
+
+			for (j = 0; j < p->kprop->count_enums; j++)
+				if (p->kprop->enums[j].value == sna_output->prop_values[i])
+					break;
+			/* there's always a matching value */
+			err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+						     XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1],
+						     FALSE, FALSE);
+			if (err != 0) {
+				xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
+					   "RRChangeOutputProperty error, %d\n", err);
+			}
+		}
+	}
+
+	if (sna_output->backlight.iface) {
+		/* Set up the backlight property, which takes effect
+		 * immediately and accepts values only within the
+		 * backlight_range.
+		 */
+		sna_output_create_ranged_atom(output, &backlight_atom,
+					      BACKLIGHT_NAME, 0,
+					      sna_output->backlight.max,
+					      sna_output->backlight_active_level,
+					      FALSE);
+		sna_output_create_ranged_atom(output,
+					      &backlight_deprecated_atom,
+					      BACKLIGHT_DEPRECATED_NAME, 0,
+					      sna_output->backlight.max,
+					      sna_output->backlight_active_level,
+					      FALSE);
+	}
+}
+
+static Bool
+sna_output_set_property(xf86OutputPtr output, Atom property,
+			RRPropertyValuePtr value)
+{
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	int i;
+
+	if (property == backlight_atom || property == backlight_deprecated_atom) {
+		INT32 val;
+		int ret = 0;
+
+		if (value->type != XA_INTEGER || value->format != 32 ||
+		    value->size != 1)
+		{
+			return FALSE;
+		}
+
+		val = *(INT32 *)value->data;
+		DBG(("%s: setting backlight to %d (max=%d)\n",
+		     __FUNCTION__, (int)val, sna_output->backlight.max));
+		if (val < 0 || val > sna_output->backlight.max)
+			return FALSE;
+
+		sna_output->backlight_active_level = val;
+		if (sna_output->dpms_mode == DPMSModeOn)
+			ret = sna_output_backlight_set(sna_output, val);
+		return ret == 0;
+	}
+
+	if (!sna_output->id)
+		return TRUE;
+
+	for (i = 0; i < sna_output->num_props; i++) {
+		struct sna_property *p = &sna_output->props[i];
+
+		if (p->atoms == NULL || p->atoms[0] != property)
+			continue;
+
+		if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
+			uint32_t val;
+
+			if (value->type != XA_INTEGER || value->format != 32 ||
+			    value->size != 1)
+				return FALSE;
+
+			val = *(uint32_t *)value->data;
+			drmModeConnectorSetProperty(sna->kgem.fd, sna_output->id,
+						    p->kprop->prop_id, (uint64_t)val);
+			return TRUE;
+		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
+			Atom atom;
+			const char *name;
+			int j;
+
+			if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+				return FALSE;
+
+			memcpy(&atom, value->data, 4);
+			name = NameForAtom(atom);
+			if (name == NULL)
+				return FALSE;
+
+			/* search for matching name string, then set its value down */
+			for (j = 0; j < p->kprop->count_enums; j++) {
+				if (!strcmp(p->kprop->enums[j].name, name)) {
+					drmModeConnectorSetProperty(sna->kgem.fd, sna_output->id,
+								    p->kprop->prop_id, p->kprop->enums[j].value);
+					return TRUE;
+				}
+			}
+			return FALSE;
+		}
+	}
+
+	/* We didn't recognise this property, just report success in order
+	 * to allow the set to continue, otherwise we break setting of
+	 * common properties like EDID.
+	 */
+	return TRUE;
+}
+
+static Bool
+sna_output_get_property(xf86OutputPtr output, Atom property)
+{
+	struct sna_output *sna_output = output->driver_private;
+	int err, i, j;
+
+	if (property == backlight_atom || property == backlight_deprecated_atom) {
+		INT32 val;
+
+		if (!sna_output->backlight.iface)
+			return FALSE;
+
+		if (sna_output->dpms_mode == DPMSModeOn) {
+			val = sna_output_backlight_get(output);
+			if (val < 0)
+				return FALSE;
+			DBG(("%s(%s): output on, reporting actual backlight value [%d]\n",
+			     __FUNCTION__, output->name, val));
+		} else {
+			val = sna_output->backlight_active_level;
+			DBG(("%s(%s): output off, reporting cached backlight value [%d]\n",
+			     __FUNCTION__, output->name, val));
+		}
+
+		err = RRChangeOutputProperty(output->randr_output, property,
+					     XA_INTEGER, 32, PropModeReplace, 1, &val,
+					     FALSE, FALSE);
+		if (err != 0) {
+			xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
+				   "RRChangeOutputProperty error, %d\n", err);
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	for (i = 0; i < sna_output->num_props; i++) {
+		struct sna_property *p = &sna_output->props[i];
+
+		if (p->atoms == NULL || p->atoms[0] != property)
+			continue;
+
+		if (sna_output->update_properties && output->scrn->vtSema)
+			update_properties(to_sna(output->scrn), sna_output);
+
+		err = 0;
+		if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
+			err = RRChangeOutputProperty(output->randr_output,
+						     property, XA_INTEGER, 32,
+						     PropModeReplace, 1,
+						     &sna_output->prop_values[i],
+						     FALSE, FALSE);
+		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
+			for (j = 0; j < p->kprop->count_enums; j++) {
+				if (p->kprop->enums[j].value == sna_output->prop_values[i])
+					break;
+			}
+			err = RRChangeOutputProperty(output->randr_output,
+						     property, XA_ATOM, 32,
+						     PropModeReplace, 1,
+						     &p->atoms[j+1],
+						     FALSE, FALSE);
+		}
+
+		if (err != 0)
+			xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
+				   "RRChangeOutputProperty error, %d\n", err);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static const xf86OutputFuncsRec sna_output_funcs = {
+	.create_resources = sna_output_create_resources,
+#ifdef RANDR_12_INTERFACE
+	.set_property = sna_output_set_property,
+	.get_property = sna_output_get_property,
+#endif
+	.dpms = sna_output_dpms,
+	.detect = sna_output_detect,
+	.mode_valid = sna_output_mode_valid,
+
+	.get_modes = sna_output_get_modes,
+	.destroy = sna_output_destroy
+};
+
+static const int subpixel_conv_table[] = {
+	SubPixelUnknown,
+	SubPixelHorizontalRGB,
+	SubPixelHorizontalBGR,
+	SubPixelVerticalRGB,
+	SubPixelVerticalBGR,
+	SubPixelNone
+};
+
+static const char * const output_names[] = {
+	/* DRM_MODE_CONNECTOR_Unknown */	"None",
+	/* DRM_MODE_CONNECTOR_VGA */		"VGA",
+	/* DRM_MODE_CONNECTOR_DVII */		"DVI",
+	/* DRM_MODE_CONNECTOR_DVID */		"DVI",
+	/* DRM_MODE_CONNECTOR_DVIA */		"DVI",
+	/* DRM_MODE_CONNECTOR_Composite */	"Composite",
+	/* DRM_MODE_CONNECTOR_SVIDEO */		"TV",
+	/* DRM_MODE_CONNECTOR_LVDS */		"LVDS",
+	/* DRM_MODE_CONNECTOR_Component */	"CTV",
+	/* DRM_MODE_CONNECTOR_9PinDIN */	"DIN",
+	/* DRM_MODE_CONNECTOR_DisplayPort */	"DP",
+	/* DRM_MODE_CONNECTOR_HDMIA */		"HDMI",
+	/* DRM_MODE_CONNECTOR_HDMIB */		"HDMI",
+	/* DRM_MODE_CONNECTOR_TV */		"TV",
+	/* DRM_MODE_CONNECTOR_eDP */		"eDP",
+	/* DRM_MODE_CONNECTOR_VIRTUAL */	"Virtual",
+	/* DRM_MODE_CONNECTOR_DSI */		"DSI",
+	/* DRM_MODE_CONNECTOR_DPI */		"DPI"
+};
+
+static bool
+output_ignored(ScrnInfoPtr scrn, const char *name)
+{
+	char monitor_name[64];
+	const char *monitor;
+	XF86ConfMonitorPtr conf;
+
+	snprintf(monitor_name, sizeof(monitor_name), "monitor-%s", name);
+	monitor = xf86findOptionValue(scrn->options, monitor_name);
+	if (!monitor)
+		monitor = name;
+
+	conf = xf86findMonitor(monitor,
+			       xf86configptr->conf_monitor_lst);
+	if (conf == NULL && XF86_CRTC_CONFIG_PTR(scrn)->num_output == 0)
+		conf = xf86findMonitor(scrn->monitor->id,
+				       xf86configptr->conf_monitor_lst);
+	if (conf == NULL)
+		return false;
+
+	return xf86CheckBoolOption(conf->mon_option_lst, "Ignore", 0);
+}
+
+static bool
+gather_encoders(struct sna *sna, uint32_t id, int count,
+		struct drm_mode_get_encoder *out)
+{
+	union compat_mode_get_connector compat_conn;
+	struct drm_mode_modeinfo dummy;
+	struct drm_mode_get_encoder enc;
+	uint32_t *ids = NULL;
+
+	DBG(("%s(%d): expected count=%d\n", __FUNCTION__, id, count));
+
+	VG_CLEAR(compat_conn);
+	VG_CLEAR(enc);
+	memset(out, 0, sizeof(*out));
+
+	do {
+		uint32_t *nids;
+
+		nids = realloc(ids, sizeof(*ids) * count);
+		if (nids == NULL) {
+			free(ids);
+			return false;
+		}
+		ids = nids;
+
+		compat_conn.conn.connector_id = id;
+		compat_conn.conn.count_props = 0;
+		compat_conn.conn.count_modes = 1; /* skip detect */
+		compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
+		compat_conn.conn.count_encoders = count;
+		compat_conn.conn.encoders_ptr = (uintptr_t)ids;
+
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &compat_conn.conn)) {
+			DBG(("%s: GETCONNECTOR[%d] failed, ret=%d\n", __FUNCTION__, id, errno));
+			compat_conn.conn.count_encoders = count = 0;
+		}
+
+		VG(VALGRIND_MAKE_MEM_DEFINED(ids, sizeof(uint32_t)*compat_conn.conn.count_encoders));
+		if (count == compat_conn.conn.count_encoders)
+			break;
+
+		count = compat_conn.conn.count_encoders;
+	} while (1);
+
+	DBG(("%s(%d): gathering %d encoders\n", __FUNCTION__, id, count));
+	for (count = 0; count < compat_conn.conn.count_encoders; count++) {
+		enc.encoder_id = ids[count];
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
+			DBG(("%s: GETENCODER[%d] failed, ret=%d\n", __FUNCTION__, ids[count], errno));
+			count = 0;
+			break;
+		}
+		DBG(("%s(%d): encoder=%d, possible_crtcs=%x, possible_clones=%x\n",
+		     __FUNCTION__, id, enc.encoder_id, enc.possible_crtcs, enc.possible_clones));
+		out->possible_crtcs |= enc.possible_crtcs;
+		out->possible_clones |= enc.possible_clones;
+
+		for (id = 0; id < sna->mode.num_real_encoder; id++) {
+			if (enc.encoder_id == sna->mode.encoders[id]) {
+				out->crtc_id |= 1 << id;
+				break;
+			}
+		}
+	}
+
+	free(ids);
+	return count > 0;
+}
+
+/* We need to map from kms encoder based possible_clones mask to X output based
+ * possible clones masking. Note that for SDVO and on Haswell with DP/HDMI we
+ * can have more than one output hanging off the same encoder.
+ */
+static void
+sna_mode_compute_possible_outputs(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int encoder_mask[32];
+	int i, j;
+
+	assert(sna->mode.num_real_output < 32);
+	assert(sna->mode.num_real_crtc < 32);
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		struct sna_output *sna_output = to_sna_output(output);
+
+		assert(sna_output);
+
+		if (sna_output->id) {
+			output->possible_clones = sna_output->possible_encoders;
+			encoder_mask[i] = sna_output->attached_encoders;
+		} else {
+			output->possible_clones = 0;
+			encoder_mask[i] = 0;
+		}
+	}
+
+	/* Convert from encoder numbering to output numbering */
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		unsigned clones;
+
+		if (output->possible_clones == 0)
+			continue;
+
+		clones = 0;
+		for (j = 0; j < sna->mode.num_real_output; j++)
+			if (i != j && output->possible_clones & encoder_mask[j])
+				clones |= 1 << j;
+		output->possible_clones = clones;
+
+		DBG(("%s: updated output '%s' %d [%d] (possible crtc:%x, possible clones:%x)\n",
+		     __FUNCTION__, output->name, i, to_connector_id(output),
+		     (uint32_t)output->possible_crtcs,
+		     (uint32_t)output->possible_clones));
+	}
+}
+
+static int name_from_path(struct sna *sna,
+			  struct sna_output *sna_output,
+			  char *name)
+{
+	struct drm_mode_get_blob blob;
+	char *path;
+	int id;
+
+	id = find_property(sna, sna_output, "PATH");
+	DBG(("%s: found? PATH=%d\n", __FUNCTION__, id));
+	if (id == -1)
+		return 0;
+
+	VG_CLEAR(blob);
+	blob.blob_id = sna_output->prop_values[id];
+	blob.length = 0;
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+		return 0;
+
+	do {
+		id = blob.length;
+		path = alloca(id + 1);
+		blob.data = (uintptr_t)path;
+		VG(memset(path, 0, id));
+		DBG(("%s: reading %d bytes for path blob\n", __FUNCTION__, id));
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+			return 0;
+	} while (id != blob.length);
+
+	path[blob.length] = '\0'; /* paranoia */
+	DBG(("%s: PATH='%s'\n", __FUNCTION__, path));
+
+	/* we only handle MST paths for now */
+	if (strncmp(path, "mst:", 4) == 0) {
+		xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+		char tmp[5], *c;
+		int n;
+
+		c = strchr(path + 4, '-');
+		if (c == NULL)
+			return 0;
+
+		id = c - (path + 4);
+		if (id + 1> 5)
+			return 0;
+
+		memcpy(tmp, path + 4, id);
+		tmp[id] = '\0';
+		id = strtoul(tmp, NULL, 0);
+
+		for (n = 0; n < sna->mode.num_real_output; n++) {
+			if (to_sna_output(config->output[n])->id == id)
+				return snprintf(name, 32, "%s-%s",
+						config->output[n]->name, c + 1);
+		}
+	}
+
+	return 0;
+}
+
+static char *fake_edid_name(xf86OutputPtr output)
+{
+	struct sna *sna = to_sna(output->scrn);
+	const char *str, *colon;
+
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
+	str = xf86GetOptValString(sna->Options, OPTION_EDID);
+#else
+	str = NULL;
+#endif
+	if (str == NULL)
+		return NULL;
+
+	do {
+		colon = strchr(str, ':');
+		if (colon == NULL)
+			return NULL;
+
+		if (strncmp(str, output->name, colon-str) == 0 &&
+		    output->name[colon-str] == '\0') {
+			char *path;
+			int len;
+
+			str = colon + 1;
+			colon = strchr(str, ',');
+			if (colon)
+				len = colon - str;
+			else
+				len = strlen(str);
+
+			path = malloc(len + 1);
+			if (path == NULL)
+				return NULL;
+
+			memcpy(path, str, len);
+			path[len] = '\0';
+			return path;
+		}
+
+		str = strchr(colon + 1, ',');
+		if (str == NULL)
+			return NULL;
+
+		str++;
+	} while (1);
+}
+
+static void
+sna_output_load_fake_edid(xf86OutputPtr output)
+{
+	struct sna_output *sna_output = output->driver_private;
+	const char *filename;
+	FILE *file;
+	void *raw;
+	int size;
+
+	filename = fake_edid_name(output);
+	if (filename == NULL)
+		return;
+
+	file = fopen(filename, "rb");
+	if (file == NULL)
+		goto err;
+
+	fseek(file, 0, SEEK_END);
+	size = ftell(file);
+	if (size % 128) {
+		fclose(file);
+		goto err;
+	}
+
+	raw = malloc(size);
+	if (raw == NULL) {
+		fclose(file);
+		free(raw);
+		goto err;
+	}
+
+	fseek(file, 0, SEEK_SET);
+	if (fread(raw, size, 1, file) != 1) {
+		fclose(file);
+		free(raw);
+		goto err;
+	}
+	fclose(file);
+
+	sna_output->fake_edid_raw = raw;
+
+	xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
+		   "Loading EDID from \"%s\" for output %s\n",
+		   filename, output->name);
+	return;
+
+err:
+	xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+		   "Could not read EDID file \"%s\" for output %s\n",
+		   filename, output->name);
+}
+
+static int
+sna_output_add(struct sna *sna, unsigned id, unsigned serial)
+{
+	ScrnInfoPtr scrn = sna->scrn;
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+	union compat_mode_get_connector compat_conn;
+	struct drm_mode_get_encoder enc;
+	struct drm_mode_modeinfo dummy;
+	struct sna_output *sna_output;
+	xf86OutputPtr *outputs, output;
+	unsigned possible_encoders, attached_encoders, possible_crtcs;
+	const char *output_name;
+	char name[32];
+	int path, len, i;
+
+	DBG(("%s(%d): serial=%d\n", __FUNCTION__, id, serial));
+
+	COMPILE_TIME_ASSERT(sizeof(struct drm_mode_get_connector) <= sizeof(compat_conn.pad));
+
+	VG_CLEAR(compat_conn);
+	memset(&enc, 0, sizeof(enc));
+
+	compat_conn.conn.connector_id = id;
+	compat_conn.conn.count_props = 0;
+	compat_conn.conn.count_modes = 1; /* skip detect */
+	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
+	compat_conn.conn.count_encoders = 1;
+	compat_conn.conn.encoders_ptr = (uintptr_t)&enc.encoder_id;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &compat_conn.conn)) {
+		DBG(("%s: GETCONNECTOR[%d] failed, ret=%d\n", __FUNCTION__, id, errno));
+		return -1;
+	}
+	assert(compat_conn.conn.connector_id == id);
+	DBG(("%s(%d): has %d associated encoders\n", __FUNCTION__, id, compat_conn.conn.count_encoders));
+
+	if (compat_conn.conn.connector_type < ARRAY_SIZE(output_names))
+		output_name = output_names[compat_conn.conn.connector_type];
+	else
+		output_name = "UNKNOWN";
+	len = snprintf(name, 32, "%s%d", output_name, compat_conn.conn.connector_type_id);
+	if (output_ignored(scrn, name))
+		return 0;
+
+	if (enc.encoder_id) {
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
+			DBG(("%s: GETENCODER[%d] failed, ret=%d\n", __FUNCTION__, enc.encoder_id, errno));
+			return 0;
+		}
+
+		possible_encoders = enc.possible_clones;
+		attached_encoders = 0;
+		for (i = 0; i < sna->mode.num_real_encoder; i++) {
+			if (enc.encoder_id == sna->mode.encoders[i]) {
+				attached_encoders = 1 << i;
+				break;
+			}
+		}
+
+		if (attached_encoders == 0) {
+			DBG(("%s: failed to find attached encoder\n", __FUNCTION__));
+			return 0;
+		}
+
+		possible_crtcs = enc.possible_crtcs;
+		assert(enc.encoder_id == compat_conn.conn.encoder_id || compat_conn.conn.encoder_id == 0);
+	} else {
+		DBG(("%s: unexpected number [%d] of encoders attached\n",
+		     __FUNCTION__, compat_conn.conn.count_encoders));
+		if (!gather_encoders(sna, id, compat_conn.conn.count_encoders, &enc)) {
+			DBG(("%s: gather encoders failed\n", __FUNCTION__));
+			return 0;
+		}
+		possible_encoders = enc.possible_clones;
+		attached_encoders = enc.crtc_id;
+		possible_crtcs = enc.possible_crtcs;
+
+		memset(&enc, 0, sizeof(enc));
+		enc.encoder_id = compat_conn.conn.encoder_id;
+		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc);
+	}
+
+	if (is_zaphod(scrn)) {
+		unsigned zaphod_crtcs;
+
+		if (!sna_zaphod_match(sna, name)) {
+			DBG(("%s: zaphod mismatch, want %s, have %s\n",
+			     __FUNCTION__,
+			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD) ?: "???",
+			     name));
+			return 0;
+		}
+
+		zaphod_crtcs = get_zaphod_crtcs(sna);
+		possible_crtcs &= zaphod_crtcs;
+		if (possible_crtcs == 0) {
+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+				   "%s is an invalid output for screen %d\n",
+				   name, scrn->confScreen->device->screen);
+			return -1;
+		}
+
+		possible_crtcs >>= ffs(zaphod_crtcs) - 1;
+	}
+
+	sna_output = calloc(sizeof(struct sna_output), 1);
+	if (!sna_output)
+		return -1;
+
+	sna_output->connector_type = compat_conn.conn.connector_type;
+	sna_output->connector_type_id = compat_conn.conn.connector_type_id;
+	sna_output->num_props = compat_conn.conn.count_props;
+	sna_output->prop_ids = malloc(sizeof(uint32_t)*compat_conn.conn.count_props);
+	sna_output->prop_values = malloc(sizeof(uint64_t)*compat_conn.conn.count_props);
+	if (sna_output->prop_ids == NULL || sna_output->prop_values == NULL) {
+		free(sna_output->prop_ids);
+		free(sna_output->prop_values);
+		free(sna_output);
+		return -1;
+	}
+
+	compat_conn.conn.count_encoders = 0;
+
+	compat_conn.conn.count_modes = 1;
+	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
+
+	compat_conn.conn.count_props = sna_output->num_props;
+	compat_conn.conn.props_ptr = (uintptr_t)sna_output->prop_ids;
+	compat_conn.conn.prop_values_ptr = (uintptr_t)sna_output->prop_values;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &compat_conn.conn)) {
+		DBG(("%s: second! GETCONNECTOR failed, ret=%d\n", __FUNCTION__, errno));
+		goto cleanup;
+	}
+	assert(compat_conn.conn.connector_id == id);
+
+	/* statically constructed property list */
+	assert(sna_output->num_props == compat_conn.conn.count_props);
+	VG(VALGRIND_MAKE_MEM_DEFINED(sna_output->prop_ids, sizeof(uint32_t)*sna_output->num_props));
+	VG(VALGRIND_MAKE_MEM_DEFINED(sna_output->prop_values, sizeof(uint64_t)*sna_output->num_props));
+
+	/* Construct name from topology, and recheck if output is acceptable */
+	path = name_from_path(sna, sna_output, name);
+	if (path) {
+		if (output_ignored(scrn, name)) {
+			len = 0;
+			goto skip;
+		}
+
+		if (is_zaphod(scrn) && !sna_zaphod_match(sna, name)) {
+			DBG(("%s: zaphod mismatch, want %s, have %s\n",
+			     __FUNCTION__,
+			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD) ?: "???",
+			     name));
+			len = 0;
+			goto skip;
+		}
+
+		len = path;
+	}
+
+	/* Check if we are dynamically reattaching an old connector */
+	if (serial) {
+		for (i = 0; i < sna->mode.num_real_output; i++) {
+			output = config->output[i];
+			if (strcmp(output->name, name) == 0) {
+				assert(output->scrn == scrn);
+				assert(output->funcs == &sna_output_funcs);
+
+				/*
+				 * If the old output is still in use, tell
+				 * the kernel to switch it off so we can
+				 * move its resources over to the new id.
+				 */
+				if (output->crtc) {
+					struct drm_mode_crtc arg = {
+						.crtc_id = __sna_crtc_id(to_sna_crtc(output->crtc)),
+					};
+					drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
+					output->crtc = NULL;
+				}
+
+				sna_output_destroy(output);
+				goto reset;
+			}
+		}
+	}
+
+	output = calloc(1, sizeof(*output) + len + 1);
+	if (!output)
+		goto cleanup;
+
+	outputs = realloc(config->output, (config->num_output + 1) * sizeof(output));
+	if (outputs == NULL) {
+		free(output);
+		goto cleanup;
+	}
+
+	output->scrn = scrn;
+	output->funcs = &sna_output_funcs;
+	output->name = (char *)(output + 1);
+	memcpy(output->name, name, len + 1);
+
+	output->use_screen_monitor = config->num_output != 0;
+	xf86OutputUseScreenMonitor(output, !output->use_screen_monitor);
+	assert(output->options);
+
+	DBG(("%s: inserting output #%d of %d\n", __FUNCTION__, sna->mode.num_real_output, config->num_output));
+	for (i = config->num_output; i > sna->mode.num_real_output; i--) {
+		outputs[i] = outputs[i-1];
+		assert(outputs[i]->driver_private == NULL);
+		outputs[i]->possible_clones <<= 1;
+	}
+
+	if (xf86ReturnOptValBool(output->options, OPTION_PRIMARY, FALSE)) {
+		memmove(outputs + 1, outputs, sizeof(output)*config->num_output);
+		outputs[0] = output;
+	} else
+		outputs[i] = output;
+	sna->mode.num_real_output++;
+	config->num_output++;
+	config->output = outputs;
+
+reset:
+	sna_output->id = compat_conn.conn.connector_id;
+	sna_output->is_panel = is_panel(compat_conn.conn.connector_type);
+	sna_output->edid_idx = find_property(sna, sna_output, "EDID");
+	sna_output->link_status_idx =
+		find_property(sna, sna_output, "link-status");
+	if (find_property(sna, sna_output, "scaling mode") != -1)
+		sna_output->add_default_modes =
+			xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
+
+	i = find_property(sna, sna_output, "DPMS");
+	if (i != -1) {
+		sna_output->dpms_id = sna_output->prop_ids[i];
+		sna_output->dpms_mode = sna_output->prop_values[i];
+		DBG(("%s: found 'DPMS' (idx=%d, id=%d), initial value=%d\n",
+		     __FUNCTION__, i, sna_output->dpms_id, sna_output->dpms_mode));
+	} else
+		sna_output->dpms_mode = DPMSModeOff;
+
+	sna_output->possible_encoders = possible_encoders;
+	sna_output->attached_encoders = attached_encoders;
+
+	output->mm_width = compat_conn.conn.mm_width;
+	output->mm_height = compat_conn.conn.mm_height;
+
+	if (compat_conn.conn.subpixel >= ARRAY_SIZE(subpixel_conv_table))
+		compat_conn.conn.subpixel = 0;
+	output->subpixel_order = subpixel_conv_table[compat_conn.conn.subpixel];
+	output->driver_private = sna_output;
+	sna_output->base = output;
+
+	backlight_init(&sna_output->backlight);
+	sna_output_backlight_init(output);
+
+	output->possible_crtcs = possible_crtcs & count_to_mask(sna->mode.num_real_crtc);
+	output->interlaceAllowed = TRUE;
+
+	sna_output_load_fake_edid(output);
+
+	if (serial) {
+		if (output->randr_output == NULL) {
+			output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), name, len, output);
+			if (output->randr_output == NULL)
+				goto cleanup;
+		}
+
+		RROutputChanged(output->randr_output, TRUE);
+		sna_output_create_resources(output);
+		RRPostPendingProperties(output->randr_output);
+
+		sna_output->serial = serial;
+	} else {
+		/* stash the active CRTC id for our probe function */
+		if (compat_conn.conn.connection != DRM_MODE_DISCONNECTED)
+			output->crtc = (void *)(uintptr_t)enc.crtc_id;
+	}
+
+	DBG(("%s: created output '%s' %d, encoder=%d (possible crtc:%x, attached encoders:%x, possible clones:%x), serial=%d, edid=%d, dpms=%d, crtc=%lu\n",
+	     __FUNCTION__, name, id, enc.encoder_id,
+	     (uint32_t)output->possible_crtcs,
+	     sna_output->attached_encoders,
+	     sna_output->possible_encoders,
+	     serial, sna_output->edid_idx, sna_output->dpms_id,
+	     (unsigned long)(uintptr_t)output->crtc));
+	assert(sna_output->id == id);
+
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
+		   "Enabled output %s\n",
+		   output->name);
+	return 1;
+
+cleanup:
+	len = -1;
+skip:
+	free(sna_output->prop_ids);
+	free(sna_output->prop_values);
+	free(sna_output);
+	return len;
+}
+
+static int output_rank(const void *A, const void *B)
+{
+	const xf86OutputPtr *a = A;
+	const xf86OutputPtr *b = B;
+	struct sna_output *sa = to_sna_output(*a);
+	struct sna_output *sb = to_sna_output(*b);
+
+	if (sa->is_panel != sb->is_panel)
+		return sb->is_panel - sa->is_panel;
+
+	return strcmp((*a)->name, (*b)->name);
+}
+
+static void sort_config_outputs(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	qsort(config->output, sna->mode.num_real_output, sizeof(*config->output), output_rank);
+	config->compat_output = 0; /* make sure it is a sane value */
+	sna_mode_compute_possible_outputs(sna);
+}
+
+static void sort_randr_outputs(struct sna *sna, ScreenPtr screen)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	rrScrPriv(screen);
+	int i;
+
+	assert(pScrPriv->numOutputs == config->num_output);
+	for (i = 0; i < config->num_output; i++) {
+		assert(config->output[i]->randr_output);
+		pScrPriv->outputs[i] = config->output[i]->randr_output;
+	}
+}
+
+static bool disable_unused_crtc(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool update = false;
+	int o, c;
+
+	DBG(("%s\n", __FUNCTION__));
+
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		xf86CrtcPtr crtc = config->crtc[c];
+
+		if (!crtc->enabled) {
+			sna_crtc_disable(crtc, false);
+			continue;
+		}
+
+		for (o = 0; o < sna->mode.num_real_output; o++) {
+			xf86OutputPtr output = config->output[o];
+			if (output->crtc == crtc)
+				break;
+		}
+
+		if (o == sna->mode.num_real_output) {
+			DBG(("%s: CRTC:%d was enabled with no outputs\n",
+			     __FUNCTION__, sna_crtc_id(crtc)));
+			crtc->enabled = false;
+			update = true;
+		}
+	}
+
+	if (update) {
+		DBG(("%s: disabling unused functions\n", __FUNCTION__));
+		xf86DisableUnusedFunctions(sna->scrn);
+	}
+
+	return update;
+}
+
+bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		struct sna_output *output = to_sna_output(config->output[i]);
+		if (output->id == id) {
+			output->reprobe = true;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool
+output_retrain_link(struct sna *sna, struct sna_output *output)
+{
+	struct sna_crtc *crtc = to_sna_crtc(output->base->crtc);
+	int crtc_x = crtc->offset & 0xffff;
+	int crtc_y = crtc->offset >> 16;
+
+	if (!crtc->bo)
+		return false;
+
+	return sna_crtc_flip(sna, crtc, crtc->bo, crtc_x, crtc_y);
+}
+
+static bool
+output_check_link(struct sna *sna, struct sna_output *output)
+{
+	uint64_t link_status;
+
+	if (!output->base->crtc)
+		return true;
+
+	if (output->link_status_idx == -1)
+		return true;
+
+#define LINK_STATUS_GOOD 0
+	link_status = output->prop_values[output->link_status_idx];
+	DBG(("%s: link_status=%d\n", __FUNCTION__, link_status));
+	if (link_status == LINK_STATUS_GOOD)
+		return true;
+
+	/* Perform a modeset as required for "link-status" = BAD */
+	if (!output_retrain_link(sna, output))
+		return false;
+
+	/* Query the "link-status" again to confirm the modeset */
+	update_properties(sna, output);
+
+	link_status = output->prop_values[output->link_status_idx];
+	DBG(("%s: link_status=%d after modeset\n", __FUNCTION__, link_status));
+	return link_status == LINK_STATUS_GOOD;
+}
+
+static bool
+output_check_status(struct sna *sna, struct sna_output *output)
+{
+	union compat_mode_get_connector compat_conn;
+	struct drm_mode_modeinfo dummy;
+	struct drm_mode_get_blob blob;
+	xf86OutputStatus status;
+	char *edid;
+
+	VG_CLEAR(compat_conn);
+
+	compat_conn.conn.connection = -1;
+	compat_conn.conn.connector_id = output->id;
+	compat_conn.conn.count_modes = 1; /* skip detect */
+	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
+	compat_conn.conn.count_encoders = 0;
+	compat_conn.conn.props_ptr = (uintptr_t)output->prop_ids;
+	compat_conn.conn.prop_values_ptr = (uintptr_t)output->prop_values;
+	compat_conn.conn.count_props = output->num_props;
+
+	if (drmIoctl(sna->kgem.fd,
+		     DRM_IOCTL_MODE_GETCONNECTOR,
+		     &compat_conn.conn) == 0)
+		output->update_properties = false;
+
+	if (!output_check_link(sna, output))
+		return false;
+
+	if (output->reprobe)
+		return false;
+
+	switch (compat_conn.conn.connection) {
+	case DRM_MODE_CONNECTED:
+		status = XF86OutputStatusConnected;
+		break;
+	case DRM_MODE_DISCONNECTED:
+		status = XF86OutputStatusDisconnected;
+		break;
+	default:
+	case DRM_MODE_UNKNOWNCONNECTION:
+		status = XF86OutputStatusUnknown;
+		break;
+	}
+	if (output->status != status)
+		return false;
+
+	if (status != XF86OutputStatusConnected)
+		return true;
+
+	if (output->num_modes != compat_conn.conn.count_modes)
+		return false;
+
+	if (output->edid_len == 0)
+		return false;
+
+	edid = alloca(output->edid_len);
+
+	VG_CLEAR(blob);
+	blob.blob_id = output->prop_values[output->edid_idx];
+	blob.length = output->edid_len;
+	blob.data = (uintptr_t)edid;
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+		return false;
+
+	if (blob.length != output->edid_len)
+		return false;
+
+	return memcmp(edid, output->edid_raw, output->edid_len) == 0;
+}
+
+void sna_mode_discover(struct sna *sna, bool tell)
+{
+	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool force = sna->flags & SNA_REPROBE;
+	struct drm_mode_card_res res;
+	uint32_t connectors[32], now;
+	unsigned changed = 0;
+	unsigned serial;
+	int i, j;
+
+	DBG(("%s()\n", __FUNCTION__));
+	sna->flags &= ~SNA_REPROBE;
+
+	VG_CLEAR(connectors);
+
+	memset(&res, 0, sizeof(res));
+	res.count_connectors = 32;
+	res.connector_id_ptr = (uintptr_t)connectors;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
+		return;
+
+	DBG(("%s: now %d (was %d) connectors, %d encoders, %d crtc\n", __FUNCTION__,
+	     res.count_connectors, sna->mode.num_real_output,
+	     res.count_encoders, res.count_crtcs));
+	if (res.count_connectors > 32)
+		res.count_connectors = 32;
+
+	assert(sna->mode.num_real_crtc == res.count_crtcs || is_zaphod(sna->scrn));
+	assert(sna->mode.max_crtc_width  == res.max_width);
+	assert(sna->mode.max_crtc_height == res.max_height);
+	assert(sna->mode.num_real_encoder == res.count_encoders);
+
+	serial = ++sna->mode.serial;
+	if (serial == 0)
+		serial = ++sna->mode.serial;
+
+	if (force) {
+		changed = 4;
+		now = 0;
+	} else
+		now = GetTimeInMillis();
+	for (i = 0; i < res.count_connectors; i++) {
+		DBG(("%s: connector[%d] = %d\n", __FUNCTION__, i, connectors[i]));
+		for (j = 0; j < sna->mode.num_real_output; j++) {
+			xf86OutputPtr output = config->output[j];
+			if (to_sna_output(output)->id == connectors[i]) {
+				DBG(("%s: found %s (id=%d)\n", __FUNCTION__, output->name, connectors[i]));
+				assert(to_sna_output(output)->id);
+				to_sna_output(output)->serial = serial;
+				break;
+			}
+		}
+		if (j == sna->mode.num_real_output) {
+			DBG(("%s: adding id=%d\n", __FUNCTION__, connectors[i]));
+			changed |= sna_output_add(sna, connectors[i], serial) > 0;
+		}
+	}
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		struct sna_output *sna_output = to_sna_output(output);
+
+		if (sna_output->id == 0)
+			continue;
+
+		if (sna_output->serial == serial) {
+			if (output_check_status(sna, sna_output)) {
+				DBG(("%s: output %s (id=%d), retained state\n",
+				     __FUNCTION__, output->name, sna_output->id));
+				sna_output->last_detect = now;
+			} else {
+				DBG(("%s: output %s (id=%d), changed state, reprobing\n",
+				     __FUNCTION__, output->name, sna_output->id));
+				sna_output->hotplug_count++;
+				sna_output->last_detect = 0;
+				changed |= 4;
+			}
+			continue;
+		}
+
+		DBG(("%s: removing output %s (id=%d), serial=%u [now %u]\n",
+		     __FUNCTION__, output->name, sna_output->id,
+		    sna_output->serial, serial));
+
+		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
+			   "Disabled output %s\n",
+			   output->name);
+		sna_output->id = 0;
+		sna_output->last_detect = 0;
+		output->crtc = NULL;
+		RROutputChanged(output->randr_output, TRUE);
+		changed |= 2;
+	}
+
+	/* Have the list of available outputs been updated? */
+	if (changed & 3) {
+		DBG(("%s: outputs changed, broadcasting\n", __FUNCTION__));
+
+		sna_mode_set_primary(sna);
+
+		/* Reorder user visible listing */
+		sort_config_outputs(sna);
+		sort_randr_outputs(sna, screen);
+
+		if (changed & 2)
+			disable_unused_crtc(sna);
+
+		xf86RandR12TellChanged(screen);
+	}
+
+	/* If anything has changed, refresh the RandR information.
+	 * Note this could recurse once from udevless RRGetInfo() probes,
+	 * but only once.
+	 */
+	if (changed && tell)
+		RRGetInfo(screen, TRUE);
+}
+
+/* Since we only probe the current mode on startup, we may not have the full
+ * list of modes available until the user explicitly requests them. Fake a
+ * hotplug event after a second after starting to fill in any missing modes.
+ */
+CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data)
+{
+	struct sna *sna = data;
+	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool reprobe = false;
+	int i;
+
+	DBG(("%s()\n", __FUNCTION__));
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		struct sna_output *sna_output = to_sna_output(output);
+
+		if (sna_output->id == 0)
+			continue;
+		if (sna_output->last_detect)
+			continue;
+		if (output->status == XF86OutputStatusDisconnected)
+			continue;
+
+		DBG(("%s: output %s connected, needs reprobe\n",
+		     __FUNCTION__, output->name));
+		reprobe = true;
+	}
+
+	if (reprobe) {
+		RRGetInfo(screen, TRUE);
+		RRTellChanged(screen);
+	}
+	free(timer);
+	return 0;
+}
+
+static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
+{
+	struct sna_pixmap *old_priv, *new_priv;
+
+	DBG(("%s\n", __FUNCTION__));
+
+	if (wedged(sna) || isGPU(sna->scrn))
+		return;
+
+	old_priv = sna_pixmap_force_to_gpu(old, MOVE_READ);
+	if (!old_priv)
+		return;
+
+	new_priv = sna_pixmap_force_to_gpu(new, MOVE_WRITE | __MOVE_SCANOUT);
+	if (!new_priv)
+		return;
+
+	if (old_priv->clear) {
+		bool ok = false;
+		if (!wedged(sna))
+			ok = sna->render.fill_one(sna, new, new_priv->gpu_bo,
+						  old_priv->clear_color,
+						  0, 0,
+						  new->drawable.width,
+						  new->drawable.height,
+						  GXcopy);
+		if (!ok) {
+			void *ptr = kgem_bo_map__gtt(&sna->kgem, new_priv->gpu_bo);
+			if (ptr)
+				memset(ptr, 0, new_priv->gpu_bo->pitch*new->drawable.height);
+		}
+		new_priv->clear = true;
+		new_priv->clear_color = old_priv->clear_color;
+	} else {
+		BoxRec box;
+		int16_t sx, sy, dx, dy;
+
+		if (new->drawable.width >= old->drawable.width &&
+		    new->drawable.height >= old->drawable.height)
+		{
+			int nx = (new->drawable.width + old->drawable.width - 1) / old->drawable.width;
+			int ny = (new->drawable.height + old->drawable.height - 1) / old->drawable.height;
+
+			box.x1 = box.y1 = 0;
+
+			dy = 0;
+			for (sy = 0; sy < ny; sy++) {
+				box.y2 = old->drawable.height;
+				if (box.y2 + dy > new->drawable.height)
+					box.y2 = new->drawable.height - dy;
+
+				dx = 0;
+				for (sx = 0; sx < nx; sx++) {
+					box.x2 = old->drawable.width;
+					if (box.x2 + dx > new->drawable.width)
+						box.x2 = new->drawable.width - dx;
+
+					(void)sna->render.copy_boxes(sna, GXcopy,
+								     &old->drawable, old_priv->gpu_bo, 0, 0,
+								     &new->drawable, new_priv->gpu_bo, dx, dy,
+								     &box, 1, 0);
+					dx += old->drawable.width;
+				}
+				dy += old->drawable.height;
+			}
+		} else {
+			box.x1 = box.y1 = 0;
+			box.x2 = min(old->drawable.width, new->drawable.width);
+			box.y2 = min(old->drawable.height, new->drawable.height);
+
+			sx = dx = 0;
+			if (box.x2 < old->drawable.width)
+				sx = (old->drawable.width - box.x2) / 2;
+			if (box.x2 < new->drawable.width)
+				dx = (new->drawable.width - box.x2) / 2;
+
+			sy = dy = 0;
+			if (box.y2 < old->drawable.height)
+				sy = (old->drawable.height - box.y2) / 2;
+			if (box.y2 < new->drawable.height)
+				dy = (new->drawable.height - box.y2) / 2;
+
+			DBG(("%s: copying box (%dx%d) from (%d, %d) to (%d, %d)\n",
+			     __FUNCTION__, box.x2, box.y2, sx, sy, dx, dy));
+
+			if (box.x2 != new->drawable.width || box.y2 != new->drawable.height) {
+				bool ok = false;
+				if (!wedged(sna))
+					ok = sna->render.fill_one(sna, new, new_priv->gpu_bo, 0,
+								  0, 0,
+								  new->drawable.width,
+								  new->drawable.height,
+								  GXclear);
+				if (!ok) {
+					void *ptr = kgem_bo_map__gtt(&sna->kgem, new_priv->gpu_bo);
+					if (ptr)
+						memset(ptr, 0, new_priv->gpu_bo->pitch*new->drawable.height);
+				}
+			}
+			(void)sna->render.copy_boxes(sna, GXcopy,
+						     &old->drawable, old_priv->gpu_bo, sx, sy,
+						     &new->drawable, new_priv->gpu_bo, dx, dy,
+						     &box, 1, 0);
+		}
+	}
+
+	sna_damage_all(&new_priv->gpu_damage, new);
+}
+
+static Bool
+sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct sna *sna = to_sna(scrn);
+	ScreenPtr screen = xf86ScrnToScreen(scrn);
+	PixmapPtr new_front;
+	int i;
+
+	DBG(("%s (%d, %d) -> (%d, %d)\n", __FUNCTION__,
+	     scrn->virtualX, scrn->virtualY,
+	     width, height));
+	assert((sna->flags & SNA_IS_HOSTED) == 0);
+
+	if (scrn->virtualX == width && scrn->virtualY == height)
+		return TRUE;
+
+	/* Paranoid defense against rogue internal calls by Xorg */
+	if (width == 0 || height == 0)
+		return FALSE;
+
+	assert(sna->front);
+	assert(screen->GetScreenPixmap(screen) == sna->front);
+
+	DBG(("%s: creating new framebuffer %dx%d\n",
+	     __FUNCTION__, width, height));
+
+	new_front = screen->CreatePixmap(screen,
+					 width, height, scrn->depth,
+					 SNA_CREATE_FB);
+	if (!new_front)
+		return FALSE;
+
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
+		   "resizing framebuffer to %dx%d\n",
+		   width, height);
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++)
+		sna_crtc_disable_shadow(sna, to_sna_crtc(config->crtc[i]));
+	assert(sna->mode.shadow_active == 0);
+	assert(!sna->mode.shadow_enabled);
+	assert(sna->mode.shadow_damage == NULL);
+	assert(sna->mode.shadow == NULL);
+
+	/* Flush pending shadow updates */
+	if (sna->mode.flip_active) {
+		DBG(("%s: waiting for %d outstanding TearFree flips\n",
+		     __FUNCTION__, sna->mode.flip_active));
+		while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
+			sna_mode_wakeup(sna);
+	}
+
+	/* Cancel a pending [un]flip (as the pixmaps no longer match) */
+	sna_present_cancel_flip(sna);
+	copy_front(sna, sna->front, new_front);
+
+	screen->SetScreenPixmap(new_front);
+	assert(screen->GetScreenPixmap(screen) == new_front);
+	assert(sna->front == new_front);
+	screen->DestroyPixmap(new_front); /* owned by screen now */
+
+	scrn->virtualX = width;
+	scrn->virtualY = height;
+	scrn->displayWidth = width;
+
+	/* Only update the CRTCs if we are in control */
+	if (!scrn->vtSema)
+		return TRUE;
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		assert(to_sna_crtc(crtc) != NULL);
+		if (to_sna_crtc(crtc)->bo == NULL)
+			continue;
+
+		if (!__sna_crtc_set_mode(crtc))
+			sna_crtc_disable(crtc, false);
+	}
+
+	sna_mode_wakeup(sna);
+	kgem_clean_scanout_cache(&sna->kgem);
+
+	return TRUE;
+}
+
+/* cursor handling */
+static void
+rotate_coord(Rotation rotation, int size,
+	     int x_dst, int y_dst,
+	     int *x_src, int *y_src)
+{
+	int t;
+
+	switch (rotation & 0xf) {
+	case RR_Rotate_0:
+		break;
+	case RR_Rotate_90:
+		t = x_dst;
+		x_dst = size - y_dst - 1;
+		y_dst = t;
+		break;
+	case RR_Rotate_180:
+		x_dst = size - x_dst - 1;
+		y_dst = size - y_dst - 1;
+		break;
+	case RR_Rotate_270:
+		t = x_dst;
+		x_dst = y_dst;
+		y_dst = size - t - 1;
+		break;
+	}
+
+	if (rotation & RR_Reflect_X)
+		x_dst = size - x_dst - 1;
+	if (rotation & RR_Reflect_Y)
+		y_dst = size - y_dst - 1;
+
+	*x_src = x_dst;
+	*y_src = y_dst;
+}
+
+static struct sna_cursor *__sna_create_cursor(struct sna *sna, int size)
+{
+	struct sna_cursor *c;
+
+	for (c = sna->cursor.cursors; c; c = c->next) {
+		if (c->ref == 0 && c->alloc >= size) {
+			__DBG(("%s: stealing handle=%d, serial=%d, rotation=%d, alloc=%d\n",
+			       __FUNCTION__, c->handle, c->serial, c->rotation, c->alloc));
+			return c;
+		}
+	}
+
+	__DBG(("%s(size=%d, num_stash=%d)\n", __FUNCTION__, size, sna->cursor.num_stash));
+
+	c = sna->cursor.stash;
+	assert(c);
+
+	c->alloc = ALIGN(size, 4096);
+	c->handle = gem_create(sna->kgem.fd, c->alloc);
+	if (c->handle == 0)
+		return NULL;
+
+	/* Old hardware uses physical addresses, which the kernel
+	 * implements in an incoherent fashion requiring a pwrite.
+	 */
+	if (sna->cursor.use_gtt) {
+		c->image = gem_mmap(sna->kgem.fd, c->handle, c->alloc);
+		if (c->image == NULL) {
+			gem_close(sna->kgem.fd, c->handle);
+			return NULL;
+		}
+	} else
+		c->image = NULL;
+
+	__DBG(("%s: handle=%d, allocated %d\n", __FUNCTION__, c->handle, size));
+
+	c->ref = 0;
+	c->serial = 0;
+	c->rotation = 0;
+	c->last_width = c->last_height = 0; /* all clear */
+	c->size = size;
+
+	sna->cursor.num_stash--;
+	sna->cursor.stash = c->next;
+
+	c->next = sna->cursor.cursors;
+	sna->cursor.cursors = c;
+
+	return c;
+}
+
+static uint32_t *get_cursor_argb(CursorPtr c)
+{
+#ifdef ARGB_CURSOR
+	return (uint32_t *)c->bits->argb;
+#else
+	return NULL;
+#endif
+}
+
+static int __cursor_size(int width, int height)
+{
+	int i, size;
+
+	i = MAX(width, height);
+	for (size = 64; size < i; size <<= 1)
+		;
+
+	return size;
+}
+
+static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
+{
+	struct sna_cursor *cursor;
+	const uint8_t *source, *mask;
+	const uint32_t *argb;
+	uint32_t *image;
+	int width, height, pitch, size, x, y;
+	bool transformed;
+	Rotation rotation;
+
+	assert(sna->cursor.ref);
+
+	cursor = to_sna_crtc(crtc)->cursor;
+	__DBG(("%s: current cursor handle=%d, serial=%d [expected %d]\n",
+	       __FUNCTION__,
+	       cursor ? cursor->handle : 0,
+	       cursor ? cursor->serial : 0,
+	       sna->cursor.serial));
+	if (cursor && cursor->serial == sna->cursor.serial) {
+		assert(cursor->size == sna->cursor.size || cursor->transformed);
+		assert(cursor->rotation == (!to_sna_crtc(crtc)->cursor_transform && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0);
+		assert(cursor->ref);
+		return cursor;
+	}
+
+	__DBG(("%s: cursor=%dx%d, pitch=%d, serial=%d, argb?=%d\n", __FUNCTION__,
+	       sna->cursor.ref->bits->width,
+	       sna->cursor.ref->bits->height,
+	       get_cursor_argb(sna->cursor.ref) ? 4*sna->cursor.ref->bits->width : BitmapBytePad(sna->cursor.ref->bits->width),
+	       sna->cursor.serial,
+	       get_cursor_argb(sna->cursor.ref) != NULL));
+
+	transformed = to_sna_crtc(crtc)->cursor_transform;
+	rotation = (!transformed && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0;
+
+	if (transformed) {
+		struct pixman_box16 box;
+
+		box.x1 = box.y1 = 0;
+		box.x2 = sna->cursor.ref->bits->width;
+		box.y2 = sna->cursor.ref->bits->height;
+
+		pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer, &box);
+		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
+		__DBG(("%s: transformed cursor %dx%d -> %dx%d\n",
+		       __FUNCTION__ ,
+		       sna->cursor.ref->bits->width,
+		       sna->cursor.ref->bits->height,
+		       box.x2 - box.x1, box.y2 - box.y1));
+	} else
+		size = sna->cursor.size;
+
+	if (crtc->transform_in_use) {
+		RRTransformPtr T = NULL;
+		struct pixman_vector v;
+
+		if (crtc->transformPresent) {
+			T = &crtc->transform;
+
+			/* Cancel any translation from this affine
+			 * transformation. We just want to rotate and scale
+			 * the cursor image.
+			 */
+			v.vector[0] = 0;
+			v.vector[1] = 0;
+			v.vector[2] = pixman_fixed_1;
+			pixman_transform_point(&crtc->transform.transform, &v);
+		}
+
+		RRTransformCompute(0, 0, size, size, crtc->rotation, T, NULL,
+				   &to_sna_crtc(crtc)->cursor_to_fb,
+				   &to_sna_crtc(crtc)->fb_to_cursor);
+		if (T)
+			pixman_f_transform_translate(
+					&to_sna_crtc(crtc)->cursor_to_fb,
+					&to_sna_crtc(crtc)->fb_to_cursor,
+					-pixman_fixed_to_double(v.vector[0]),
+					-pixman_fixed_to_double(v.vector[1]));
+
+		__DBG(("%s: cursor_to_fb [%f %f %f, %f %f %f, %f %f %f]\n",
+		       __FUNCTION__,
+		       to_sna_crtc(crtc)->cursor_to_fb.m[0][0],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[0][1],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[0][2],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[1][0],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[1][1],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[1][2],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[2][0],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[2][1],
+		       to_sna_crtc(crtc)->cursor_to_fb.m[2][2]));
+	}
+
+	/* Don't allow phys cursor sharing */
+	if (sna->cursor.use_gtt && !transformed) {
+		for (cursor = sna->cursor.cursors; cursor; cursor = cursor->next) {
+			if (cursor->serial == sna->cursor.serial &&
+			    cursor->rotation == rotation &&
+			    !cursor->transformed) {
+				__DBG(("%s: reusing handle=%d, serial=%d, rotation=%d, size=%d\n",
+				       __FUNCTION__, cursor->handle, cursor->serial, cursor->rotation, cursor->size));
+				assert(cursor->size == sna->cursor.size);
+				return cursor;
+			}
+		}
+	}
+
+	cursor = to_sna_crtc(crtc)->cursor;
+	if (cursor && cursor->alloc < 4*size*size)
+		cursor = NULL;
+
+	if (cursor == NULL) {
+		cursor = __sna_create_cursor(sna, 4*size*size);
+		if (cursor == NULL) {
+			DBG(("%s: failed to allocate cursor\n", __FUNCTION__));
+			return NULL;
+		}
+	}
+
+	width  = sna->cursor.ref->bits->width;
+	height = sna->cursor.ref->bits->height;
+	source = sna->cursor.ref->bits->source;
+	mask = sna->cursor.ref->bits->mask;
+	argb = get_cursor_argb(sna->cursor.ref);
+	pitch = BitmapBytePad(width);
+
+	image = cursor->image;
+	if (image == NULL || transformed) {
+		image = sna->cursor.scratch;
+		cursor->last_width = cursor->last_height = size;
+	}
+	if (size > cursor->size ||
+	    width < cursor->last_width ||
+	    height < cursor->last_height ||
+	    rotation != cursor->rotation)
+		memset(image, 0, 4*size*size);
+	if (rotation == RR_Rotate_0) {
+		if (argb == NULL) {
+			for (y = 0; y < height; y++) {
+				uint32_t *p = image + y*size;
+				for (x = 0; x < width; x++) {
+					int byte = x / 8;
+					uint8_t bit = 1 << (x & 7);
+					uint32_t pixel;
+
+					if (mask[byte] & bit) {
+						if (source[byte] & bit)
+							pixel = sna->cursor.fg;
+						else
+							pixel = sna->cursor.bg;
+					} else
+						pixel = 0;
+
+					*p++ = pixel;
+				}
+				mask += pitch;
+				source += pitch;
+			}
+			if (transformed) {
+				__DBG(("%s: Applying affine BLT to bitmap\n", __FUNCTION__));
+				affine_blt(image, cursor->image, 32,
+					   0, 0, width, height, size * 4,
+					   0, 0, size, size, size * 4,
+					   &to_sna_crtc(crtc)->cursor_to_fb);
+				image = cursor->image;
+			}
+		} else if (transformed) {
+			__DBG(("%s: Applying affine BLT to ARGB\n", __FUNCTION__));
+			affine_blt(argb, cursor->image, 32,
+				   0, 0, width, height, width * 4,
+				   0, 0, size, size, size * 4,
+				   &to_sna_crtc(crtc)->cursor_to_fb);
+			image = cursor->image;
+		} else
+			memcpy_blt(argb, image, 32,
+				   width * 4, size * 4,
+				   0, 0,
+				   0, 0,
+				   width, height);
+	} else {
+		for (y = 0; y < size; y++)
+			for (x = 0; x < size; x++) {
+				uint32_t pixel;
+				int xin, yin;
+
+				rotate_coord(rotation, size, x, y, &xin, &yin);
+				if (xin < width && yin < height)
+					if (argb == NULL) {
+						int byte = xin / 8;
+						int bit = xin & 7;
+						if (mask[yin*pitch + byte] & (1 << bit)) {
+							if (source[yin*pitch + byte] & (1 << bit))
+								pixel = sna->cursor.fg;
+							else
+								pixel = sna->cursor.bg;
+						} else
+							pixel = 0;
+					} else
+						pixel = argb[yin * width + xin];
+				else
+					pixel = 0;
+				image[y * size + x] = pixel;
+			}
+	}
+
+	if (image != cursor->image) {
+		struct drm_i915_gem_pwrite pwrite;
+
+		VG_CLEAR(pwrite);
+		pwrite.handle = cursor->handle;
+		pwrite.offset = 0;
+		pwrite.size = 4*size*size;
+		pwrite.data_ptr = (uintptr_t)image;
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite))
+			__DBG(("%s: cursor update (pwrite) failed: %d\n", __FUNCTION__, errno));
+	}
+
+	cursor->size = size;
+	cursor->rotation = rotation;
+	cursor->transformed = transformed;
+	cursor->serial = sna->cursor.serial;
+	if (transformed) {
+		/* mark the transformed rectangle as dirty, not input */
+		cursor->last_width = size;
+		cursor->last_height = size;
+	} else {
+		cursor->last_width = width;
+		cursor->last_height = height;
+	}
+	return cursor;
+}
+
+static unsigned char *
+sna_realize_cursor(xf86CursorInfoPtr info, CursorPtr cursor)
+{
+	return NULL;
+}
+
+static void __restore_swcursor(ScrnInfoPtr scrn)
+{
+	struct sna *sna = to_sna(scrn);
+
+	DBG(("%s: attempting to restore SW cursor\n", __FUNCTION__));
+	xf86CursorResetCursor(scrn->pScreen);
+
+	/* Try to switch back to the HW cursor on the next cursor update */
+	sna->cursor.disable = false;
+
+	RemoveBlockAndWakeupHandlers((void *)__restore_swcursor,
+				     (void *)NoopDDA,
+				     scrn);
+}
+
+static void restore_swcursor(struct sna *sna)
+{
+	sna->cursor.info->HideCursor(sna->scrn);
+
+	/* XXX Force the cursor to be restored (avoiding recursion) */
+	FreeCursor(sna->cursor.ref, None);
+	sna->cursor.ref = NULL;
+
+	RegisterBlockAndWakeupHandlers((void *)__restore_swcursor,
+				       (void *)NoopDDA,
+				       sna->scrn);
+}
+
+static void
+sna_show_cursors(ScrnInfoPtr scrn)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct sna *sna = to_sna(scrn);
+	struct kmsg kmsg;
+	int sigio, c;
+
+	DBG(("%s: cursor?=%d\n", __FUNCTION__, sna->cursor.ref != NULL));
+	if (sna->cursor.ref == NULL)
+		return;
+
+	kmsg_open(&kmsg);
+	sigio = sigio_block();
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[c];
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		struct drm_mode_cursor arg;
+		struct sna_cursor *cursor;
+
+		assert(sna_crtc != NULL);
+		if (sna_crtc->bo == NULL)
+			continue;
+
+		if (!crtc->cursor_in_range) {
+			DBG(("%s: skipping cursor outside CRTC (pipe=%d)\n",
+			     __FUNCTION__, sna_crtc_pipe(crtc)));
+			continue;
+		}
+
+		cursor = __sna_get_cursor(sna, crtc);
+		if (cursor == NULL ||
+		    (sna_crtc->cursor == cursor && sna_crtc->last_cursor_size == cursor->size)) {
+			DBG(("%s: skipping cursor already show on CRTC (pipe=%d)\n",
+			     __FUNCTION__, sna_crtc_pipe(crtc)));
+			continue;
+		}
+
+		DBG(("%s: CRTC pipe=%d, handle->%d\n", __FUNCTION__,
+		     sna_crtc_pipe(crtc), cursor->handle));
+
+		VG_CLEAR(arg);
+		arg.flags = DRM_MODE_CURSOR_BO;
+		arg.crtc_id = __sna_crtc_id(sna_crtc);
+		arg.width = arg.height = cursor->size;
+		arg.handle = cursor->handle;
+
+		if (!FAIL_CURSOR_IOCTL &&
+		    drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
+			if (sna_crtc->cursor) {
+				assert(sna_crtc->cursor->ref > 0);
+				sna_crtc->cursor->ref--;
+			}
+			cursor->ref++;
+			sna_crtc->cursor = cursor;
+			sna_crtc->last_cursor_size = cursor->size;
+		} else {
+			ERR(("%s: failed to show cursor on CRTC:%d [pipe=%d], disabling hwcursor: errno=%d\n",
+			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc), errno));
+			sna->cursor.disable = true;
+		}
+	}
+	sigio_unblock(sigio);
+	sna->cursor.active = true;
+	kmsg_close(&kmsg, sna->cursor.disable);
+
+	if (unlikely(sna->cursor.disable))
+		restore_swcursor(sna);
+}
+
+static void
+sna_set_cursor_colors(ScrnInfoPtr scrn, int _bg, int _fg)
+{
+	struct sna *sna = to_sna(scrn);
+	uint32_t fg = _fg, bg = _bg;
+
+	__DBG(("%s(bg=%08x, fg=%08x)\n", __FUNCTION__, bg, fg));
+
+	/* Save ARGB versions of these colors */
+	fg |= 0xff000000;
+	bg |= 0xff000000;
+	if (fg == sna->cursor.fg && bg == sna->cursor.bg)
+		return;
+
+	sna->cursor.fg = fg;
+	sna->cursor.bg = bg;
+
+	if (sna->cursor.ref == NULL)
+		return;
+
+	if (get_cursor_argb(sna->cursor.ref))
+		return;
+
+	sna->cursor.serial++;
+	__DBG(("%s: serial->%d\n", __FUNCTION__, sna->cursor.serial));
+
+	sna_show_cursors(scrn);
+}
+
+static void
+sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc)
+{
+	struct drm_mode_cursor arg;
+	int sigio;
+
+	if (!crtc->cursor)
+		return;
+
+	sigio = sigio_block();
+	if (crtc->cursor) {
+		DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, __sna_crtc_id(crtc), crtc->cursor->handle));
+		assert(crtc->cursor->ref > 0);
+		crtc->cursor->ref--;
+		crtc->cursor = NULL;
+		crtc->last_cursor_size = 0;
+
+		VG_CLEAR(arg);
+		arg.flags = DRM_MODE_CURSOR_BO;
+		arg.crtc_id = __sna_crtc_id(crtc);
+		arg.width = arg.height = 0;
+		arg.handle = 0;
+
+		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
+	}
+	sigio_unblock(sigio);
+}
+
+static void
+sna_disable_cursors(ScrnInfoPtr scrn)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct sna *sna = to_sna(scrn);
+	int sigio, c;
+
+	DBG(("%s\n", __FUNCTION__));
+
+	sigio = sigio_block();
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		assert(to_sna_crtc(xf86_config->crtc[c]));
+		sna_crtc_disable_cursor(sna, to_sna_crtc(xf86_config->crtc[c]));
+	}
+	sigio_unblock(sigio);
+}
+
+static void
+sna_hide_cursors(ScrnInfoPtr scrn)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct sna *sna = to_sna(scrn);
+	struct sna_cursor *cursor, **prev;
+	int sigio, c;
+
+	DBG(("%s\n", __FUNCTION__));
+	sna->cursor.active = false;
+
+	sigio = sigio_block();
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		assert(to_sna_crtc(xf86_config->crtc[c]));
+		sna_crtc_disable_cursor(sna, to_sna_crtc(xf86_config->crtc[c]));
+	}
+
+	for (prev = &sna->cursor.cursors; (cursor = *prev) != NULL; ) {
+		assert(cursor->ref == 0);
+
+		if (cursor->serial == sna->cursor.serial) {
+			prev = &cursor->next;
+			continue;
+		}
+
+		*prev = cursor->next;
+		if (cursor->image)
+			munmap(cursor->image, cursor->alloc);
+		gem_close(sna->kgem.fd, cursor->handle);
+
+		cursor->next = sna->cursor.stash;
+		sna->cursor.stash = cursor;
+		sna->cursor.num_stash++;
+	}
+
+	sigio_unblock(sigio);
+}
+
+static void
+sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct sna *sna = to_sna(scrn);
+	struct kmsg kmsg;
+	int sigio, c;
+
+	__DBG(("%s(%d, %d), cursor? %d\n", __FUNCTION__,
+	       x, y, sna->cursor.ref!=NULL));
+	if (sna->cursor.ref == NULL)
+		return;
+
+	kmsg_open(&kmsg);
+	sigio = sigio_block();
+	sna->cursor.last_x = x;
+	sna->cursor.last_y = y;
+
+	/* undo what xf86HWCurs did to the coordinates */
+	x += scrn->frameX0;
+	y += scrn->frameY0;
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[c];
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		struct sna_cursor *cursor = NULL;
+		struct drm_mode_cursor arg;
+
+		assert(sna_crtc != NULL);
+
+		VG_CLEAR(arg);
+		arg.flags = 0;
+		arg.crtc_id = __sna_crtc_id(sna_crtc);
+		arg.handle = 0;
+
+		if (sna_crtc->bo == NULL)
+			goto disable;
+
+		cursor = __sna_get_cursor(sna, crtc);
+		if (cursor == NULL)
+			cursor = sna_crtc->cursor;
+		if (cursor == NULL) {
+			__DBG(("%s: failed to grab cursor, disabling\n", __FUNCTION__));
+			goto disable;
+		}
+
+		if (crtc->transform_in_use) {
+			int xhot = sna->cursor.ref->bits->xhot;
+			int yhot = sna->cursor.ref->bits->yhot;
+			struct pict_f_vector v, hot;
+
+			v.v[0] = x + xhot + .5;
+			v.v[1] = y + yhot + .5;
+			v.v[2] = 1.;
+			pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &v);
+
+			hot.v[0] = xhot;
+			hot.v[1] = yhot;
+			hot.v[2] = 1.;
+			pixman_f_transform_point(&sna_crtc->fb_to_cursor, &hot);
+
+			arg.x = floor(v.v[0] - hot.v[0]);
+			arg.y = floor(v.v[1] - hot.v[1]);
+		} else {
+			arg.x = x - crtc->x;
+			arg.y = y - crtc->y;
+		}
+
+		if (arg.x < crtc->mode.HDisplay && arg.x > -sna->cursor.size &&
+		    arg.y < crtc->mode.VDisplay && arg.y > -sna->cursor.size) {
+			if (sna_crtc->cursor != cursor || sna_crtc->last_cursor_size != cursor->size) {
+				arg.flags |= DRM_MODE_CURSOR_BO;
+				arg.handle = cursor->handle;
+			}
+
+			arg.width = arg.height = cursor->size;
+			arg.flags |= DRM_MODE_CURSOR_MOVE;
+			crtc->cursor_in_range = true;
+		} else {
+			crtc->cursor_in_range = false;
+disable:
+			if (sna_crtc->cursor) {
+				arg.flags = DRM_MODE_CURSOR_BO;
+				arg.width = arg.height = 0;
+			}
+			cursor = NULL;
+		}
+
+		__DBG(("%s: CRTC:%d (%d, %d), handle=%d, flags=%x (old cursor handle=%d), move? %d, update handle? %d\n",
+		       __FUNCTION__, __sna_crtc_id(sna_crtc), arg.x, arg.y, arg.handle, arg.flags, sna_crtc->cursor ? sna_crtc->cursor->handle : 0,
+		       arg.flags & DRM_MODE_CURSOR_MOVE, arg.flags & DRM_MODE_CURSOR_BO));
+
+		if (arg.flags == 0)
+			continue;
+
+		if (!FAIL_CURSOR_IOCTL &&
+		    drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
+			if (arg.flags & DRM_MODE_CURSOR_BO) {
+				if (sna_crtc->cursor) {
+					assert(sna_crtc->cursor->ref > 0);
+					sna_crtc->cursor->ref--;
+				}
+				sna_crtc->cursor = cursor;
+				if (cursor) {
+					sna_crtc->last_cursor_size = cursor->size;
+					cursor->ref++;
+				} else
+					sna_crtc->last_cursor_size = 0;
+			}
+		} else {
+			ERR(("%s: failed to update cursor on CRTC:%d [pipe=%d], disabling hwcursor: errno=%d\n",
+			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc), errno));
+			/* XXX How to force switch back to SW cursor?
+			 * Right now we just want until the next cursor image
+			 * change, which is fairly frequent.
+			 */
+			sna->cursor.disable = true;
+		}
+	}
+	sigio_unblock(sigio);
+	kmsg_close(&kmsg, sna->cursor.disable);
+
+	if (unlikely(sna->cursor.disable))
+		restore_swcursor(sna);
+}
+
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2)
+static Bool
+sna_load_cursor_argb2(ScrnInfoPtr scrn, CursorPtr cursor)
+{
+	return TRUE;
+}
+
+static Bool
+sna_load_cursor_image2(ScrnInfoPtr scrn, unsigned char *src)
+{
+	return TRUE;
+}
+#endif
+
+static void
+sna_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor)
+{
+}
+
+static void
+sna_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
+{
+}
+
+static bool
+sna_cursor_preallocate(struct sna *sna)
+{
+	while (sna->cursor.num_stash < 0) {
+		struct sna_cursor *cursor = malloc(sizeof(*cursor));
+		if (!cursor)
+			return false;
+
+		cursor->next = sna->cursor.stash;
+		sna->cursor.stash = cursor;
+
+		sna->cursor.num_stash++;
+	}
+
+	return true;
+}
+
+static bool
+transformable_cursor(struct sna *sna, CursorPtr cursor)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+		struct pixman_box16 box;
+		int size;
+
+		if (!to_sna_crtc(crtc)->hwcursor) {
+			DBG(("%s: hwcursor disabled on CRTC:%d [pipe=%d]\n",
+			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc)));
+			return false;
+		}
+
+		if (!sna->cursor.use_gtt || !sna->cursor.scratch) {
+			DBG(("%s: unable to use GTT curosor access [%d] or no scratch [%d]\n",
+			     __FUNCTION__, sna->cursor.use_gtt, sna->cursor.scratch));
+			return false;
+		}
+
+		box.x1 = box.y1 = 0;
+		box.x2 = cursor->bits->width;
+		box.y2 = cursor->bits->height;
+
+		if (!pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer,
+					       &box)) {
+			DBG(("%s: unable to transform bounds\n", __FUNCTION__));
+			return false;
+		}
+
+		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
+		if (size > sna->cursor.max_size) {
+			DBG(("%s: transformed cursor size=%d too large, max=%d\n",
+			     __FUNCTION__, size, sna->cursor.max_size));
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static Bool
+sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
+{
+	struct sna *sna = to_sna_from_screen(screen);
+
+	DBG(("%s (%dx%d)?\n", __FUNCTION__,
+	     cursor->bits->width, cursor->bits->height));
+
+	if (sna->cursor.disable)
+		return FALSE;
+
+	/* cursors are invariant */
+	if (cursor == sna->cursor.ref)
+		return TRUE;
+
+	if (sna->cursor.ref) {
+		FreeCursor(sna->cursor.ref, None);
+		sna->cursor.ref = NULL;
+	}
+
+	sna->cursor.size =
+		__cursor_size(cursor->bits->width, cursor->bits->height);
+	if (sna->cursor.size > sna->cursor.max_size) {
+		DBG(("%s: cursor size=%d too large, max %d: using sw cursor\n",
+		     __FUNCTION__, sna->cursor.size, sna->cursor.max_size));
+		return FALSE;
+	}
+
+	if (sna->mode.rr_active && !transformable_cursor(sna, cursor)) {
+		DBG(("%s: RandR active [%d] and non-transformable cursor: using sw cursor\n",
+		     __FUNCTION__, sna->mode.rr_active));
+		return FALSE;
+	}
+
+	if (!sna_cursor_preallocate(sna)) {
+		DBG(("%s: cursor preallocation failed: using sw cursor\n", __FUNCTION__));
+		return FALSE;
+	}
+
+	sna->cursor.ref = cursor;
+	cursor->refcnt++;
+	sna->cursor.serial++;
+
+	DBG(("%s(%dx%d): ARGB?=%d, serial->%d, size->%d\n", __FUNCTION__,
+	       cursor->bits->width,
+	       cursor->bits->height,
+	       get_cursor_argb(cursor) != NULL,
+	       sna->cursor.serial,
+	       sna->cursor.size));
+	return TRUE;
+}
+
+static void
+sna_cursor_pre_init(struct sna *sna)
+{
+	struct local_get_cap {
+		uint64_t name;
+		uint64_t value;
+	} cap;
+	int v;
+
+	if (sna->mode.num_real_crtc == 0)
+		return;
+
+#define LOCAL_IOCTL_GET_CAP	DRM_IOWR(0x0c, struct local_get_cap)
+#ifndef DRM_CAP_CURSOR_WIDTH
+#define DRM_CAP_CURSOR_WIDTH	0x8
+#endif
+#ifndef DRM_CAP_CURSOR_HEIGHT
+#define DRM_CAP_CURSOR_HEIGHT	0x9
+#endif
+
+#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
+
+	sna->cursor.max_size = 64;
+
+	cap.value = 0;
+	cap.name = DRM_CAP_CURSOR_WIDTH;
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_GET_CAP, &cap) == 0)
+		sna->cursor.max_size = cap.value;
+
+	cap.name = DRM_CAP_CURSOR_HEIGHT;
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_GET_CAP, &cap) == 0 &&
+	    cap.value < sna->cursor.max_size)
+		sna->cursor.max_size = cap.value;
+
+	v = -1; /* No param uses the sign bit, reserve it for errors */
+	if (sna->kgem.gen >= 033) {
+		v = 1;
+	} else {
+		drm_i915_getparam_t gp = {
+			I915_PARAM_HAS_COHERENT_PHYS_GTT,
+			&v,
+		};
+		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	}
+	sna->cursor.use_gtt = v > 0;
+	DBG(("%s: cursor updates use_gtt?=%d\n",
+	     __FUNCTION__, sna->cursor.use_gtt));
+
+	sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4);
+	if (!sna->cursor.scratch && !sna->cursor.use_gtt)
+		sna->cursor.max_size = 0;
+
+	sna->cursor.num_stash = -sna->mode.num_real_crtc;
+
+	xf86DrvMsg(sna->scrn->scrnIndex, X_PROBED,
+		   "Using a maximum size of %dx%d for hardware cursors\n",
+		   sna->cursor.max_size, sna->cursor.max_size);
+}
+
+static void
+sna_cursor_close(struct sna *sna)
+{
+	sna->cursor.serial = 0;
+	sna_hide_cursors(sna->scrn);
+
+	while (sna->cursor.stash) {
+		struct sna_cursor *cursor = sna->cursor.stash;
+		sna->cursor.stash = cursor->next;
+		free(cursor);
+	}
+
+	sna->cursor.num_stash = -sna->mode.num_real_crtc;
+}
+
+bool
+sna_cursors_init(ScreenPtr screen, struct sna *sna)
+{
+	xf86CursorInfoPtr cursor_info;
+
+	if (sna->cursor.max_size == 0)
+		return false;
+
+	cursor_info = xf86CreateCursorInfoRec();
+	if (cursor_info == NULL)
+		return false;
+
+	cursor_info->MaxWidth = sna->cursor.max_size;
+	cursor_info->MaxHeight = sna->cursor.max_size;
+	cursor_info->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+			      HARDWARE_CURSOR_UPDATE_UNHIDDEN |
+			      HARDWARE_CURSOR_ARGB);
+
+	cursor_info->RealizeCursor = sna_realize_cursor;
+	cursor_info->SetCursorColors = sna_set_cursor_colors;
+	cursor_info->SetCursorPosition = sna_set_cursor_position;
+	cursor_info->LoadCursorImage = sna_load_cursor_image;
+	cursor_info->HideCursor = sna_hide_cursors;
+	cursor_info->ShowCursor = sna_show_cursors;
+	cursor_info->UseHWCursor = sna_use_hw_cursor;
+#ifdef ARGB_CURSOR
+	cursor_info->UseHWCursorARGB = sna_use_hw_cursor;
+	cursor_info->LoadCursorARGB = sna_load_cursor_argb;
+#endif
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,3)
+	cursor_info->LoadCursorImageCheck = sna_load_cursor_image2;
+#ifdef ARGB_CURSOR
+	cursor_info->LoadCursorARGBCheck = sna_load_cursor_argb2;
+#endif
+#endif
+
+	if (!xf86InitCursor(screen, cursor_info)) {
+		xf86DestroyCursorInfoRec(cursor_info);
+		return false;
+	}
+
+	sna->cursor.info = cursor_info;
+	return true;
+}
+
+static void
+sna_cursors_reload(struct sna *sna)
+{
+	DBG(("%s: active?=%d\n", __FUNCTION__, sna->cursor.active));
+	if (sna->cursor.active)
+		sna_set_cursor_position(sna->scrn,
+					sna->cursor.last_x,
+					sna->cursor.last_y);
+}
+
+static void
+sna_cursors_fini(struct sna *sna)
+{
+	if (sna->cursor.info) {
+		xf86DestroyCursorInfoRec(sna->cursor.info);
+		sna->cursor.info = NULL;
+	}
+
+	if (sna->cursor.ref) {
+		FreeCursor(sna->cursor.ref, None);
+		sna->cursor.ref = NULL;
+	}
+}
+
+static bool
+sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x, int y)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	struct drm_mode_crtc arg;
+	uint32_t output_ids[32];
+	int output_count = 0;
+	int i;
+
+	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), bo->handle));
+
+	assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
+	assert(crtc->bo);
+	assert(crtc->kmode.clock);
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+
+		if (output->crtc != crtc->base)
+			continue;
+
+		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
+		     __FUNCTION__, output->name, i, to_connector_id(output),
+		     __sna_crtc_id(crtc), __sna_crtc_pipe(crtc),
+		     (uint32_t)output->possible_crtcs,
+		     (uint32_t)output->possible_clones));
+
+		assert(output->possible_crtcs & (1 << __sna_crtc_pipe(crtc)) ||
+		       is_zaphod(sna->scrn));
+
+		output_ids[output_count] = to_connector_id(output);
+		if (++output_count == ARRAY_SIZE(output_ids))
+			return false;
+	}
+	assert(output_count);
+
+	VG_CLEAR(arg);
+	arg.crtc_id = __sna_crtc_id(crtc);
+	arg.fb_id = fb_id(bo);
+	assert(arg.fb_id);
+	arg.x = x;
+	arg.y = y;
+	arg.set_connectors_ptr = (uintptr_t)output_ids;
+	arg.count_connectors = output_count;
+	arg.mode = crtc->kmode;
+	arg.mode_valid = 1;
+
+	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d across %d outputs [%d...]\n",
+	     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc),
+	     arg.mode.hdisplay,
+	     arg.mode.vdisplay,
+	     arg.x, arg.y,
+	     arg.mode.clock,
+	     arg.fb_id,
+	     output_count, output_count ? output_ids[0] : 0));
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
+		return false;
+
+	crtc->offset = y << 16 | x;
+	__kgem_bo_clear_dirty(bo);
+	return true;
+}
+
+static void sna_mode_restore(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int error = 0;
+	int i;
+
+	assert(!sna->mode.hidden);
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		assert(to_sna_crtc(crtc) != NULL);
+		if (to_sna_crtc(crtc)->bo == NULL)
+			continue;
+
+		assert(crtc->enabled);
+		if (!__sna_crtc_set_mode(crtc)) {
+			sna_crtc_disable(crtc, false);
+			error++;
+		}
+	}
+	sna_mode_wakeup(sna);
+	while (sna->mode.flip_active && sna_mode_wakeup(sna))
+		;
+	update_flush_interval(sna);
+	sna_cursors_reload(sna);
+	sna->mode.dirty = false;
+
+	if (error)
+		xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+			   "Failed to restore display configuration\n");
+}
+
+bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *crtc = config->crtc[i]->driver_private;
+
+		if (crtc->bo == NULL)
+			continue;
+
+		if (crtc->bo == bo)
+			continue;
+
+		return true;
+	}
+
+	return false;
+}
+
+int
+sna_page_flip(struct sna *sna,
+	      struct kgem_bo *bo,
+	      sna_flip_handler_t handler,
+	      void *data)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	const int width = sna->scrn->virtualX;
+	const int height = sna->scrn->virtualY;
+	int sigio;
+	int count = 0;
+	int i;
+
+	DBG(("%s: handle %d attached\n", __FUNCTION__, bo->handle));
+	assert(bo->refcnt);
+
+	assert((sna->flags & SNA_IS_HOSTED) == 0);
+	assert(sna->mode.flip_active == 0);
+	assert(sna->mode.front_active);
+	assert(!sna->mode.hidden);
+	assert(sna->scrn->vtSema);
+
+	if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0)
+		return 0;
+
+	kgem_bo_submit(&sna->kgem, bo);
+	__kgem_bo_clear_dirty(bo);
+
+	sigio = sigio_block();
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *crtc = config->crtc[i]->driver_private;
+		struct drm_mode_crtc_page_flip arg;
+		uint32_t crtc_offset;
+		int fixup;
+
+		DBG(("%s: crtc %d id=%d, pipe=%d active? %d\n",
+		     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->bo != NULL));
+		if (crtc->bo == NULL)
+			continue;
+		assert(!crtc->transform);
+		assert(!crtc->slave_pixmap);
+		assert(crtc->bo->active_scanout);
+		assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
+		assert(crtc->flip_bo == NULL);
+
+		assert_crtc_fb(sna, crtc);
+		if (data == NULL && crtc->bo == bo)
+			goto next_crtc;
+
+		arg.crtc_id = __sna_crtc_id(crtc);
+		arg.fb_id = get_fb(sna, bo, width, height);
+		if (arg.fb_id == 0) {
+			assert(count == 0);
+			break;
+		}
+
+		fixup = 0;
+		crtc_offset = crtc->base->y << 16 | crtc->base->x;
+
+		if (bo->pitch != crtc->bo->pitch || crtc_offset != crtc->offset) {
+			DBG(("%s: changing pitch (%d == %d) or offset (%x == %x)\n",
+			     __FUNCTION__,
+			     bo->pitch, crtc->bo->pitch,
+			     crtc_offset, crtc->offset));
+fixup_flip:
+			fixup = 1;
+			if (crtc->bo != bo && sna_crtc_flip(sna, crtc, bo, crtc->base->x, crtc->base->y)) {
+update_scanout:
+				DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
+				     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout,
+				     bo->handle, bo->active_scanout));
+				assert(crtc->bo->active_scanout);
+				assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
+				crtc->bo->active_scanout--;
+				kgem_bo_destroy(&sna->kgem, crtc->bo);
+
+				if (crtc->shadow_bo) {
+					kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+					crtc->shadow_bo = NULL;
+				}
+
+				crtc->bo = kgem_bo_reference(bo);
+				crtc->bo->active_scanout++;
+
+				if (data == NULL)
+					goto next_crtc;
+
+				/* queue a flip in order to send the event */
+			} else
+				goto error;
+		}
+
+		/* Only the reference crtc will finally deliver its page flip
+		 * completion event. All other crtc's events will be discarded.
+		 */
+		if (data) {
+			arg.user_data = (uintptr_t)crtc;
+			arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
+		} else {
+			arg.user_data = 0;
+			arg.flags = DRM_MODE_PAGE_FLIP_ASYNC;
+		}
+		arg.reserved = 0;
+
+retry_flip:
+		DBG(("%s: crtc %d id=%d, pipe=%d  --> fb %d\n",
+		     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), arg.fb_id));
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
+			ERR(("%s: pageflip failed with err=%d\n", __FUNCTION__, errno));
+
+			if (errno == EBUSY) {
+				struct drm_mode_crtc mode;
+
+				memset(&mode, 0, sizeof(mode));
+				mode.crtc_id = __sna_crtc_id(crtc);
+				drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode);
+
+				DBG(("%s: crtc=%d, valid?=%d, fb attached?=%d, expected=%d\n",
+				     __FUNCTION__,
+				     mode.crtc_id, mode.mode_valid,
+				     mode.fb_id, fb_id(crtc->bo)));
+
+				if (mode.fb_id != fb_id(crtc->bo))
+					goto fixup_flip;
+
+				if (count == 0)
+					break;
+
+				DBG(("%s: throttling on busy flip / waiting for kernel to catch up\n", __FUNCTION__));
+				drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_THROTTLE, 0);
+				sna->kgem.need_throttle = false;
+
+				goto retry_flip;
+			}
+
+			if (!fixup)
+				goto fixup_flip;
+
+error:
+			xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+					"page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
+					__sna_crtc_id(crtc), __sna_crtc_pipe(crtc), data ? "synchronous": "asynchronous");
+
+			if (count || crtc->bo == bo)
+				sna_mode_restore(sna);
+
+			sna->flags &= ~(data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP);
+			count = 0;
+			break;
+		}
+
+		if (data) {
+			assert(crtc->flip_bo == NULL);
+			assert(handler);
+			crtc->flip_handler = handler;
+			crtc->flip_data = data;
+			crtc->flip_bo = kgem_bo_reference(bo);
+			crtc->flip_bo->active_scanout++;
+			crtc->flip_serial = crtc->mode_serial;
+			crtc->flip_pending = true;
+			sna->mode.flip_active++;
+
+			DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
+			     __FUNCTION__, __sna_crtc_id(crtc), crtc->flip_bo->handle, crtc->flip_bo->active_scanout, crtc->flip_serial));
+		} else
+			goto update_scanout;
+next_crtc:
+		count++;
+	}
+	sigio_unblock(sigio);
+
+	DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
+	return count;
+}
+
+static const xf86CrtcConfigFuncsRec sna_mode_funcs = {
+	.resize = sna_mode_resize,
+};
+
+static void set_size_range(struct sna *sna)
+{
+	/* We lie slightly as we expect no single monitor to exceed the
+	 * crtc limits, so if the mode exceeds the scanout restrictions,
+	 * we will quietly convert that to per-crtc pixmaps.
+	 */
+	xf86CrtcSetSizeRange(sna->scrn, 8, 8, INT16_MAX, INT16_MAX);
+}
+
+#if HAS_GAMMA
+static void set_gamma(uint16_t *curve, int size, double value)
+{
+	int i;
+
+	value = 1/value;
+	for (i = 0; i < size; i++)
+		curve[i] = 256*(size-1)*pow(i/(double)(size-1), value);
+}
+
+static void output_set_gamma(xf86OutputPtr output, xf86CrtcPtr crtc)
+{
+	XF86ConfMonitorPtr mon = output->conf_monitor;
+
+	if (!mon)
+		return;
+
+	DBG(("%s: red=%f\n", __FUNCTION__, mon->mon_gamma_red));
+	if (mon->mon_gamma_red >= GAMMA_MIN &&
+	    mon->mon_gamma_red <= GAMMA_MAX &&
+	    mon->mon_gamma_red != 1.0)
+		set_gamma(crtc->gamma_red, crtc->gamma_size,
+			  mon->mon_gamma_red);
+
+	DBG(("%s: green=%f\n", __FUNCTION__, mon->mon_gamma_green));
+	if (mon->mon_gamma_green >= GAMMA_MIN &&
+	    mon->mon_gamma_green <= GAMMA_MAX &&
+	    mon->mon_gamma_green != 1.0)
+		set_gamma(crtc->gamma_green, crtc->gamma_size,
+			  mon->mon_gamma_green);
+
+	DBG(("%s: blue=%f\n", __FUNCTION__, mon->mon_gamma_blue));
+	if (mon->mon_gamma_blue >= GAMMA_MIN &&
+	    mon->mon_gamma_blue <= GAMMA_MAX &&
+	    mon->mon_gamma_blue != 1.0)
+		set_gamma(crtc->gamma_blue, crtc->gamma_size,
+			  mon->mon_gamma_blue);
+}
+
+static bool
+crtc_get_gamma_lut(xf86CrtcPtr crtc,
+		   CARD16 *red, CARD16 *green, CARD16 *blue, int size)
+{
+
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct drm_color_lut *lut = sna_crtc->gamma_lut;
+	struct drm_mode_get_blob blob;
+	int lut_size, i;
+
+	DBG(("%s: gamma_size %d\n", __FUNCTION__, size));
+
+	memset(&blob, 0, sizeof(blob));
+	blob.blob_id = sna_crtc->gamma_lut_blob;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+		return false;
+
+	lut_size = blob.length / sizeof(lut[0]);
+
+	if (lut_size == 0 ||
+	    lut_size > max(sna_crtc->gamma_lut_size, 256))
+		return false;
+
+	blob.data = (uintptr_t)lut;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+		return false;
+
+	for (i = 0; i < size; i++) {
+		struct drm_color_lut *entry =
+			&lut[i * (lut_size - 1) / (size - 1)];
+
+		red[i] = entry->red;
+		green[i] = entry->green;
+		blue[i] = entry->blue;
+	}
+
+	return red[size - 1] &&
+		green[size - 1] &&
+		blue[size - 1];
+}
+
+static bool crtc_get_gamma_legacy(xf86CrtcPtr crtc,
+				  CARD16 *red,
+				  CARD16 *green,
+				  CARD16 *blue,
+				  int size)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct drm_mode_crtc_lut lut = {
+		.crtc_id = __sna_crtc_id(sna_crtc),
+		.gamma_size = size,
+		.red = (uintptr_t)red,
+		.green = (uintptr_t)green,
+		.blue = (uintptr_t)blue,
+	};
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETGAMMA, &lut) != 0)
+		return false;
+
+	VG(VALGRIND_MAKE_MEM_DEFINED(red, size*sizeof(red[0])));
+	VG(VALGRIND_MAKE_MEM_DEFINED(green, size*sizeof(green[0])));
+	VG(VALGRIND_MAKE_MEM_DEFINED(blue, size*sizeof(blue[0])));
+
+	return red[size - 1] &&
+		green[size - 1] &&
+		blue[size - 1];
+}
+
+static void crtc_init_gamma(xf86CrtcPtr crtc)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	uint16_t *gamma;
+	int size;
+
+	assert(sna_crtc);
+
+	size = sna_crtc->gamma_lut_size;
+	if (!size)
+		size = 256;
+
+	/* Initialize the gamma ramps */
+	gamma = NULL;
+	if (crtc->gamma_size == size)
+		gamma = crtc->gamma_red;
+	if (gamma == NULL)
+		gamma = malloc(3 * size * sizeof(uint16_t));
+	if (gamma) {
+		uint16_t *red = gamma;
+		uint16_t *green = gamma + size;
+		uint16_t *blue = gamma + 2 * size;
+		bool gamma_set;
+
+		if (sna_crtc->gamma_lut_size)
+			gamma_set = crtc_get_gamma_lut(crtc, red,
+						       green, blue, size);
+		else
+			gamma_set = crtc_get_gamma_legacy(crtc, red,
+							  green, blue, size);
+
+		DBG(("%s: CRTC:%d, pipe=%d: gamma set?=%d\n",
+		     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
+		     gamma_set));
+		if (!gamma_set) {
+			int i;
+
+			for (i = 0; i < size; i++) {
+				uint16_t val = i * 0xffff / (size - 1);
+
+				red[i] = val;
+				green[i] = val;
+				blue[i] = val;
+			}
+		}
+
+		if (red != crtc->gamma_red) {
+			free(crtc->gamma_red);
+			crtc->gamma_red = red;
+			crtc->gamma_green = green;
+			crtc->gamma_blue = blue;
+			crtc->gamma_size = size;
+		}
+	}
+}
+#else
+static void output_set_gamma(xf86OutputPtr output, xf86CrtcPtr crtc) { }
+static void crtc_init_gamma(xf86CrtcPtr crtc) { }
+#endif
+
+static const char *preferred_mode(xf86OutputPtr output)
+{
+	const char *mode;
+
+	mode = xf86GetOptValString(output->options, OPTION_PREFERRED_MODE);
+	if (mode)
+		return mode;
+
+	if (output->scrn->display->modes && *output->scrn->display->modes)
+		return *output->scrn->display->modes;
+
+	return NULL;
+}
+
+static bool sna_probe_initial_configuration(struct sna *sna)
+{
+	ScrnInfoPtr scrn = sna->scrn;
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+	int crtc_active, crtc_enabled;
+	int width, height;
+	int i, j;
+
+	assert((sna->flags & SNA_IS_HOSTED) == 0);
+
+	if ((sna->flags & SNA_IS_SLAVED) == 0) {
+		const int user_overrides[] = {
+			OPTION_POSITION,
+			OPTION_BELOW,
+			OPTION_RIGHT_OF,
+			OPTION_ABOVE,
+			OPTION_LEFT_OF,
+			OPTION_ROTATE,
+			OPTION_PANNING,
+		};
+		if (xf86ReturnOptValBool(sna->Options, OPTION_REPROBE, FALSE)) {
+			DBG(("%s: user requests reprobing\n", __FUNCTION__));
+			return false;
+		}
+
+		/* First scan through all outputs and look for user overrides */
+		for (i = 0; i < sna->mode.num_real_output; i++) {
+			xf86OutputPtr output = config->output[i];
+
+			for (j = 0; j < ARRAY_SIZE(user_overrides); j++) {
+				if (xf86GetOptValString(output->options, user_overrides[j])) {
+					DBG(("%s: user placement [%d] for %s\n",
+					     __FUNCTION__,
+					     user_overrides[j],
+					     output->name));
+					return false;
+				}
+			}
+		}
+	}
+
+	/* Copy the existing modes on each CRTCs */
+	crtc_active = crtc_enabled = 0;
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		struct drm_mode_crtc mode;
+
+		crtc->enabled = FALSE;
+		crtc->desiredMode.status = MODE_NOMODE;
+
+		crtc_init_gamma(crtc);
+
+		/* Retrieve the current mode */
+		VG_CLEAR(mode);
+		mode.crtc_id = __sna_crtc_id(sna_crtc);
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
+			continue;
+
+		DBG(("%s: CRTC:%d, pipe=%d: has mode?=%d\n", __FUNCTION__,
+		     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
+		     mode.mode_valid && mode.mode.clock));
+
+		if (!mode.mode_valid || mode.mode.clock == 0)
+			continue;
+
+		mode_from_kmode(scrn, &mode.mode, &crtc->desiredMode);
+		crtc->desiredRotation = sna_crtc->primary.rotation.current;
+		crtc->desiredX = mode.x;
+		crtc->desiredY = mode.y;
+		crtc->desiredTransformPresent = FALSE;
+		crtc_active++;
+	}
+
+	/* Reconstruct outputs pointing to active CRTC */
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		uint32_t crtc_id;
+
+		assert(to_sna_output(output));
+
+		crtc_id = (uintptr_t)output->crtc;
+		output->crtc = NULL;
+		output->status = XF86OutputStatusUnknown;
+		if (sna->flags & SNA_IS_SLAVED)
+			continue;
+
+		if (crtc_id == 0) {
+			DBG(("%s: not using output %s, disconnected\n",
+			     __FUNCTION__, output->name));
+			continue;
+		}
+
+		if (xf86ReturnOptValBool(output->options, OPTION_DISABLE, 0)) {
+			DBG(("%s: not using output %s, manually disabled\n",
+			     __FUNCTION__, output->name));
+			continue;
+		}
+
+		for (j = 0; j < sna->mode.num_real_crtc; j++) {
+			xf86CrtcPtr crtc = config->crtc[j];
+
+			assert(to_sna_crtc(crtc));
+			if (sna_crtc_id(crtc) != crtc_id)
+				continue;
+
+			if (crtc->desiredMode.status == MODE_OK) {
+				DisplayModePtr M;
+				const char *pref;
+
+				pref = preferred_mode(output);
+				if (pref && strcmp(pref, crtc->desiredMode.name)) {
+					DBG(("%s: output %s user requests a different preferred mode %s, found %s\n",
+					     __FUNCTION__, output->name, pref, crtc->desiredMode.name));
+					return false;
+				}
+
+				xf86DrvMsg(scrn->scrnIndex, X_PROBED,
+					   "Output %s using initial mode %s on pipe %d\n",
+					   output->name,
+					   crtc->desiredMode.name,
+					   sna_crtc_pipe(crtc));
+
+				output->crtc = crtc;
+				output->status = XF86OutputStatusConnected;
+				crtc->enabled = TRUE;
+				crtc_enabled++;
+
+				output_set_gamma(output, crtc);
+
+				if (output->conf_monitor) {
+					output->mm_width = output->conf_monitor->mon_width;
+					output->mm_height = output->conf_monitor->mon_height;
+				}
+
+#if 0
+				sna_output_attach_edid(output);
+				sna_output_attach_tile(output);
+#endif
+
+				if (output->mm_width == 0 || output->mm_height == 0) {
+					output->mm_height = (crtc->desiredMode.VDisplay * 254) / (10*DEFAULT_DPI);
+					output->mm_width = (crtc->desiredMode.HDisplay * 254) / (10*DEFAULT_DPI);
+				}
+
+				M = calloc(1, sizeof(DisplayModeRec));
+				if (M) {
+					*M = crtc->desiredMode;
+					M->name = strdup(M->name);
+					output->probed_modes =
+						xf86ModesAdd(output->probed_modes, M);
+				}
+			}
+
+			break;
+		}
+
+		if (j == sna->mode.num_real_crtc) {
+			/* Can not find the earlier associated CRTC, bail */
+			DBG(("%s: existing setup conflicts with output assignment (Zaphod), reprobing\n",
+			     __FUNCTION__));
+			return false;
+		}
+	}
+
+	if (crtc_active != crtc_enabled) {
+		DBG(("%s: only enabled %d out of %d active CRTC, forcing a reconfigure\n",
+		     __FUNCTION__, crtc_enabled, crtc_active));
+		return false;
+	}
+
+	width = height = 0;
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+		int w, h;
+
+		if (!crtc->enabled)
+			continue;
+
+		w = crtc->desiredX + crtc->desiredMode.HDisplay;
+		if (w > width)
+			width = w;
+		h = crtc->desiredY + crtc->desiredMode.VDisplay;
+		if (h > height)
+			height = h;
+	}
+
+	/* Prefer the native panel size if any */
+	if (!width || !height) {
+		for (i = 0; i < sna->mode.num_real_output; i++) {
+			xf86OutputPtr output = config->output[i];
+			struct sna_output *sna_output = to_sna_output(output);
+
+			if (!sna_output->is_panel)
+				continue;
+
+			DBG(("%s: querying panel '%s' for preferred unattached size\n",
+			     __FUNCTION__, output->name));
+
+			if (sna_output_detect(output) != XF86OutputStatusConnected)
+				continue;
+
+			if (sna_output->num_modes == 0)
+				continue;
+
+			width  = sna_output->modes[0].hdisplay;
+			height = sna_output->modes[0].vdisplay;
+
+			DBG(("%s: panel '%s' is %dx%d\n",
+			     __FUNCTION__, output->name, width, height));
+			break;
+		}
+	}
+
+	if (!width || !height) {
+		width = 1024;
+		height = 768;
+	}
+
+	scrn->display->frameX0 = 0;
+	scrn->display->frameY0 = 0;
+	scrn->display->virtualX = width;
+	scrn->display->virtualY = height;
+
+	scrn->virtualX = width;
+	scrn->virtualY = height;
+
+	xf86SetScrnInfoModes(sna->scrn);
+	DBG(("%s: SetScrnInfoModes = %p\n", __FUNCTION__, scrn->modes));
+	return scrn->modes != NULL;
+}
+
+static void
+sanitize_outputs(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	for (i = 0; i < config->num_output; i++)
+		config->output[i]->crtc = NULL;
+}
+
+static bool has_flip(struct sna *sna)
+{
+	drm_i915_getparam_t gp;
+	int v;
+
+	if (sna->flags & SNA_NO_FLIP)
+		return false;
+
+	v = 0;
+
+	VG_CLEAR(gp);
+	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
+	gp.value = &v;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GETPARAM, &gp))
+		return false;
+
+	VG(VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v)));
+	return v > 0;
+}
+
+static bool has_flip__async(struct sna *sna)
+{
+#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
+	struct local_get_cap {
+		uint64_t name;
+		uint64_t value;
+	} cap = { .name = DRM_CAP_ASYNC_PAGE_FLIP, };
+
+	if (sna->flags & SNA_NO_FLIP)
+		return false;
+
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_GET_CAP, &cap) == 0)
+		return cap.value > 0;
+
+	return false;
+}
+
+static void
+probe_capabilities(struct sna *sna)
+{
+	sna->flags &= ~(SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP);
+	if (has_flip(sna))
+		sna->flags |= SNA_HAS_FLIP;
+	if (has_flip__async(sna) && (sna->flags & SNA_TEAR_FREE) == 0)
+		sna->flags |= SNA_HAS_ASYNC_FLIP;
+	DBG(("%s: page flips? %s, async? %s\n", __FUNCTION__,
+	     sna->flags & SNA_HAS_FLIP ? "enabled" : "disabled",
+	     sna->flags & SNA_HAS_ASYNC_FLIP ? "enabled" : "disabled"));
+}
+
+void
+sna_crtc_config_notify(ScreenPtr screen)
+{
+	struct sna *sna = to_sna_from_screen(screen);
+
+	DBG(("%s(dirty?=%d)\n", __FUNCTION__, sna->mode.dirty));
+	if (!sna->mode.dirty)
+		return;
+
+	if (disable_unused_crtc(sna)) {
+		/* This will have recursed, so simply bail at this point */
+		assert(sna->mode.dirty == false);
+#ifdef RANDR_12_INTERFACE
+		xf86RandR12TellChanged(screen);
+#endif
+		return;
+	}
+
+	/* Flush any events completed by the modeset */
+	sna_mode_wakeup(sna);
+
+	update_flush_interval(sna);
+	sna->cursor.disable = false; /* Reset HW cursor until the next fail */
+	sna_cursors_reload(sna);
+
+	probe_capabilities(sna);
+	sna_present_update(sna);
+
+	/* Allow TearFree to come back on when everything is off */
+	if (!sna->mode.front_active && sna->flags & SNA_WANT_TEAR_FREE) {
+		if ((sna->flags & SNA_TEAR_FREE) == 0)
+			DBG(("%s: enable TearFree next modeset\n",
+			     __FUNCTION__));
+
+		sna->flags |= SNA_TEAR_FREE;
+	}
+
+	sna->mode.dirty = false;
+}
+
+#if HAS_PIXMAP_SHARING
+#define sna_setup_provider(scrn) xf86ProviderSetup(scrn, NULL, "Intel")
+#else
+#define sna_setup_provider(scrn)
+#endif
+
+bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
+{
+	drmModeResPtr res;
+	int num_fake = 0;
+	int i;
+
+	if (sna->flags & SNA_IS_HOSTED) {
+		sna_setup_provider(scrn);
+		return true;
+	}
+
+	probe_capabilities(sna);
+	sna->mode.hidden = !isGPU(scrn); /* No DPMS passthrough */
+
+	if (!xf86GetOptValInteger(sna->Options, OPTION_VIRTUAL, &num_fake))
+		num_fake = 1;
+
+	res = drmModeGetResources(sna->kgem.fd);
+	if (res &&
+	    (res->count_crtcs == 0 ||
+	     res->count_encoders == 0 ||
+	     res->count_connectors == 0)) {
+		drmModeFreeResources(res);
+		res = NULL;
+	}
+	if (res) {
+		xf86CrtcConfigPtr xf86_config;
+
+		DBG(("%s: found %d CRTC, %d encoders, %d connectors\n",
+		     __FUNCTION__, res->count_crtcs, res->count_encoders, res->count_connectors));
+
+		assert(res->count_crtcs);
+		assert(res->count_connectors);
+
+		xf86CrtcConfigInit(scrn, &sna_mode_funcs);
+
+		xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+		xf86_config->xf86_crtc_notify = sna_crtc_config_notify;
+		xf86_config->compat_output = 0;
+
+		for (i = 0; i < res->count_crtcs; i++)
+			if (!sna_crtc_add(scrn, res->crtcs[i]))
+				return false;
+
+		sna->mode.num_real_crtc = xf86_config->num_crtc;
+
+		sna->mode.num_real_encoder = res->count_encoders;
+		sna->mode.encoders = res->encoders;
+		res->encoders = NULL;
+
+		for (i = 0; i < res->count_connectors; i++)
+			if (sna_output_add(sna, res->connectors[i], 0) < 0)
+				return false;
+
+		sna->mode.num_real_output = xf86_config->num_output;
+
+		sna->mode.max_crtc_width  = res->max_width;
+		sna->mode.max_crtc_height = res->max_height;
+
+		RegionEmpty(&sna->mode.shadow_region);
+		RegionEmpty(&sna->mode.shadow_cancel);
+		list_init(&sna->mode.shadow_crtc);
+
+		drmModeFreeResources(res);
+
+		sna_cursor_pre_init(sna);
+		sna_backlight_pre_init(sna);
+
+		set_size_range(sna);
+	} else {
+		if (num_fake == 0)
+			num_fake = 1;
+	}
+
+	if (!sna_mode_fake_init(sna, num_fake))
+		return false;
+
+	sna->mode.shadow_size = 256;
+	sna->mode.shadow_events = malloc(sna->mode.shadow_size * sizeof(struct drm_event_vblank));
+	if (!sna->mode.shadow_events)
+		return false;
+
+	if (!sna_probe_initial_configuration(sna)) {
+		xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+		sanitize_outputs(sna);
+		if (config->num_crtc && config->num_output) {
+			if (!xf86ReturnOptValBool(config->output[0]->options,
+						  OPTION_PRIMARY, FALSE))
+				sort_config_outputs(sna);
+			xf86InitialConfiguration(scrn, TRUE);
+		}
+	}
+	sort_config_outputs(sna);
+
+	sna_setup_provider(scrn);
+	return scrn->modes != NULL;
+}
+
+bool
+sna_mode_wants_tear_free(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool found = false;
+	FILE *file;
+	int i;
+
+	file = fopen("/sys/module/i915/parameters/enable_fbc", "r");
+	if (file) {
+		int fbc_enabled = 0;
+		int value;
+
+		if (fscanf(file, "%d", &value) == 1)
+			fbc_enabled = value > 0;
+		fclose(file);
+
+		DBG(("%s: module parameter 'enable_fbc' enabled? %d\n",
+		     __FUNCTION__, fbc_enabled));
+
+		if (fbc_enabled)
+			return true;
+	}
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		struct sna_output *output = to_sna_output(config->output[i]);
+		int id = find_property(sna, output, "Panel Self-Refresh");
+		if (id == -1)
+			continue;
+
+		found = true;
+		if (output->prop_values[id] != -1) {
+			DBG(("%s: Panel Self-Refresh detected on %s\n",
+			     __FUNCTION__, config->output[i]->name));
+			return true;
+		}
+	}
+
+	if (!found) {
+		file = fopen("/sys/module/i915/parameters/enable_psr", "r");
+		if (file) {
+			int psr_enabled = 0;
+			int value;
+
+			if (fscanf(file, "%d", &value) == 1)
+				psr_enabled = value > 0;
+			fclose(file);
+
+			DBG(("%s: module parameter 'enable_psr' enabled? %d\n",
+			     __FUNCTION__, psr_enabled));
+
+			if (psr_enabled)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+void
+sna_mode_set_primary(struct sna *sna)
+{
+#ifdef RANDR_12_INTERFACE
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	rrScrPrivPtr rr = rrGetScrPriv(xf86ScrnToScreen(sna->scrn));
+	int i;
+
+	if (rr == NULL || rr->primaryOutput)
+		return;
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+
+		if (!xf86ReturnOptValBool(output->options, OPTION_PRIMARY, FALSE))
+			continue;
+
+		DBG(("%s: setting PrimaryOutput %s\n", __FUNCTION__, output->name));
+		rr->primaryOutput = output->randr_output;
+		RROutputChanged(rr->primaryOutput, FALSE);
+		rr->layoutChanged = TRUE;
+		break;
+	}
+#endif
+}
+
+bool
+sna_mode_disable(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	if (sna->flags & SNA_IS_HOSTED)
+		return false;
+
+	if (!sna->scrn->vtSema)
+		return false;
+
+	sna_disable_cursors(sna->scrn);
+	for (i = 0; i < sna->mode.num_real_crtc; i++)
+		sna_crtc_disable(config->crtc[i], false);
+	assert(sna->mode.front_active == 0);
+
+	sna_mode_wakeup(sna);
+	kgem_clean_scanout_cache(&sna->kgem);
+	return true;
+}
+
+void
+sna_mode_enable(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	DBG(("%s\n", __FUNCTION__));
+
+	if (sna->flags & SNA_IS_HOSTED)
+		return;
+
+	if (!sna->scrn->vtSema)
+		return;
+
+	if (sna->mode.hidden) {
+		DBG(("%s: hidden outputs\n", __FUNCTION__));
+		return;
+	}
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		DBG(("%s: crtc[%d].enabled?=%d\n", __FUNCTION__, i, crtc->enabled));
+		assert(to_sna_crtc(crtc) != NULL);
+		if (!crtc->enabled)
+			continue;
+
+		if (crtc->mode.Clock == 0)
+			continue;
+
+		__sna_crtc_set_mode(crtc);
+	}
+
+	update_flush_interval(sna);
+	sna_cursors_reload(sna);
+	sna->mode.dirty = false;
+}
+
+static void sna_randr_close(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int n;
+
+	/* The RR structs are freed early during CloseScreen as they
+	 * are tracked as Resources. However, we may be tempted to
+	 * access them during shutdown so decouple them now.
+	 */
+	  for (n = 0; n < config->num_output; n++)
+		  config->output[n]->randr_output = NULL;
+
+	  for (n = 0; n < config->num_crtc; n++)
+		  config->crtc[n]->randr_crtc = NULL;
+}
+
+void
+sna_mode_close(struct sna *sna)
+{
+	sna_randr_close(sna);
+	sna_mode_wakeup(sna);
+
+	if (sna->flags & SNA_IS_HOSTED)
+		return;
+
+	sna_mode_reset(sna);
+
+	sna_cursor_close(sna);
+	sna_cursors_fini(sna);
+
+	sna_backlight_close(sna);
+	sna->mode.dirty = false;
+}
+
+void
+sna_mode_fini(struct sna *sna)
+{
+	free(sna->mode.encoders);
+}
+
+static bool sna_box_intersect(BoxPtr r, const BoxRec *a, const BoxRec *b)
+{
+	r->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+	r->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+	if (r->x1 >= r->x2)
+		return false;
+
+	r->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+	r->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+	DBG(("%s: (%d, %d), (%d, %d) intersect (%d, %d), (%d, %d) = (%d, %d), (%d, %d)\n",
+	     __FUNCTION__,
+	     a->x1, a->y1, a->x2, a->y2,
+	     b->x1, b->y1, b->x2, b->y2,
+	     r->x1, r->y1, r->x2, r->y2));
+	if (r->y1 >= r->y2)
+		return false;
+
+	return true;
+}
+
+static int sna_box_area(const BoxRec *box)
+{
+	return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
+}
+
+/*
+ * Return the crtc covering 'box'. If two crtcs cover a portion of
+ * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+ * with greater coverage
+ */
+xf86CrtcPtr
+sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	xf86CrtcPtr best_crtc = NULL;
+	int best_coverage = -1, c;
+
+	if (sna->flags & SNA_IS_HOSTED)
+		return NULL;
+
+	/* If we do not own the VT, we do not own the CRTC either */
+	if (!sna->scrn->vtSema) {
+		DBG(("%s: none, VT switched\n", __FUNCTION__));
+		return NULL;
+	}
+
+	if (sna->mode.hidden) {
+		DBG(("%s: none, hidden outputs\n", __FUNCTION__));
+		return NULL;
+	}
+
+	DBG(("%s for box=(%d, %d), (%d, %d)\n",
+	     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
+
+	if (desired == NULL) {
+		ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
+		rrScrPrivPtr rr = rrGetScrPriv(screen);
+		if (rr && rr->primaryOutput && rr->primaryOutput->pScreen == screen) {
+			xf86OutputPtr output = rr->primaryOutput->devPrivate;
+			DBG(("%s: have PrimaryOutput? %d marking as desired\n", __FUNCTION__, output->crtc != NULL));
+			desired = output->crtc;
+		}
+		assert(!desired || desired->scrn == sna->scrn);
+	}
+	if (desired && to_sna_crtc(desired) && to_sna_crtc(desired)->bo) {
+		BoxRec cover_box;
+		if (sna_box_intersect(&cover_box, &desired->bounds, box)) {
+			DBG(("%s: box overlaps desired crtc: (%d, %d), (%d, %d)\n",
+			     __FUNCTION__,
+			     cover_box.x1, cover_box.y1,
+			     cover_box.x2, cover_box.y2));
+			return desired;
+		}
+		best_crtc = desired;
+		best_coverage = 0;
+	}
+
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		xf86CrtcPtr crtc = config->crtc[c];
+		BoxRec cover_box;
+		int coverage;
+
+		assert(to_sna_crtc(crtc));
+
+		/* If the CRTC is off, treat it as not covering */
+		if (to_sna_crtc(crtc)->bo == NULL) {
+			DBG(("%s: crtc %d off, skipping\n", __FUNCTION__, c));
+			continue;
+		}
+
+		DBG(("%s: crtc %d: (%d, %d), (%d, %d)\n",
+		     __FUNCTION__, c,
+		     crtc->bounds.x1, crtc->bounds.y1,
+		     crtc->bounds.x2, crtc->bounds.y2));
+		if (!memcmp(box, &crtc->bounds, sizeof(*box))) {
+			DBG(("%s: box exactly matches crtc [%d]\n",
+			     __FUNCTION__, c));
+			return crtc;
+		}
+
+		coverage = 0;
+		if (sna_box_intersect(&cover_box, &crtc->bounds, box))
+			coverage = sna_box_area(&cover_box);
+
+		DBG(("%s: box instersects (%d, %d), (%d, %d) of crtc %d\n",
+		     __FUNCTION__,
+		     cover_box.x1, cover_box.y1,
+		     cover_box.x2, cover_box.y2,
+		     c));
+
+		DBG(("%s: box covers %d of crtc %d\n",
+		     __FUNCTION__, coverage, c));
+		if (coverage > best_coverage) {
+			best_crtc = crtc;
+			best_coverage = coverage;
+		}
+	}
+	DBG(("%s: best crtc = %p, coverage = %d\n",
+	     __FUNCTION__, best_crtc, best_coverage));
+	return best_crtc;
+}
+
+static xf86CrtcPtr first_active_crtc(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int n;
+
+	for (n = 0; n < sna->mode.num_real_crtc; n++) {
+		xf86CrtcPtr crtc = config->crtc[n];
+		if (to_sna_crtc(crtc)->bo)
+			return crtc;
+	}
+
+	/* No active, use the first as a placeholder */
+	if (sna->mode.num_real_crtc)
+		return config->crtc[0];
+
+	return NULL;
+}
+
+xf86CrtcPtr sna_primary_crtc(struct sna *sna)
+{
+	rrScrPrivPtr rr = rrGetScrPriv(xf86ScrnToScreen(sna->scrn));
+	if (rr && rr->primaryOutput) {
+		xf86OutputPtr output = rr->primaryOutput->devPrivate;
+		if (output->crtc &&
+		    output->scrn == sna->scrn &&
+		    to_sna_crtc(output->crtc))
+			return output->crtc;
+	}
+
+	return first_active_crtc(sna);
+}
+
+#define MI_LOAD_REGISTER_IMM			(0x22<<23)
+
+static bool sna_emit_wait_for_scanline_hsw(struct sna *sna,
+					   xf86CrtcPtr crtc,
+					   int pipe, int y1, int y2,
+					   bool full_height)
+{
+	uint32_t event;
+	uint32_t *b;
+
+	if (!sna->kgem.has_secure_batches)
+		return false;
+
+	b = kgem_get_batch(&sna->kgem);
+	sna->kgem.nbatch += 17;
+
+	switch (pipe) {
+	default: assert(0); /* fall through */
+	case 0: event = 1 << 0; break;
+	case 1: event = 1 << 8; break;
+	case 2: event = 1 << 14; break;
+	}
+
+	b[0] = MI_LOAD_REGISTER_IMM | 1;
+	b[1] = 0x44050; /* DERRMR */
+	b[2] = ~event;
+	b[3] = MI_LOAD_REGISTER_IMM | 1;
+	b[4] = 0xa188; /* FORCEWAKE_MT */
+	b[5] = 2 << 16 | 2;
+
+	/* The documentation says that the LOAD_SCAN_LINES command
+	 * always comes in pairs. Don't ask me why. */
+	switch (pipe) {
+	default: assert(0); /* fall through */
+	case 0: event = 0 << 19; break;
+	case 1: event = 1 << 19; break;
+	case 2: event = 4 << 19; break;
+	}
+	b[8] = b[6] = MI_LOAD_SCAN_LINES_INCL | event;
+	b[9] = b[7] = (y1 << 16) | (y2-1);
+
+	switch (pipe) {
+	default: assert(0); /* fall through */
+	case 0: event = 1 << 0; break;
+	case 1: event = 1 << 8; break;
+	case 2: event = 1 << 14; break;
+	}
+	b[10] = MI_WAIT_FOR_EVENT | event;
+
+	b[11] = MI_LOAD_REGISTER_IMM | 1;
+	b[12] = 0xa188; /* FORCEWAKE_MT */
+	b[13] = 2 << 16;
+	b[14] = MI_LOAD_REGISTER_IMM | 1;
+	b[15] = 0x44050; /* DERRMR */
+	b[16] = ~0;
+
+	sna->kgem.batch_flags |= I915_EXEC_SECURE;
+	return true;
+}
+
+static bool sna_emit_wait_for_scanline_ivb(struct sna *sna,
+					   xf86CrtcPtr crtc,
+					   int pipe, int y1, int y2,
+					   bool full_height)
+{
+	uint32_t event, *b;
+
+	if (!sna->kgem.has_secure_batches)
+		return false;
+
+	assert(y1 >= 0);
+	assert(y2 > y1);
+	assert(sna->kgem.mode);
+
+	/* Always program one less than the desired value */
+	if (--y1 < 0)
+		y1 = crtc->bounds.y2;
+	y2--;
+
+	switch (pipe) {
+	default:
+		assert(0);
+		/* fall through */
+	case 0:
+		event = 1 << (full_height ? 3 : 0);
+		break;
+	case 1:
+		event = 1 << (full_height ? 11 : 8);
+		break;
+	case 2:
+		event = 1 << (full_height ? 21 : 14);
+		break;
+	}
+
+	b = kgem_get_batch(&sna->kgem);
+
+	/* Both the LRI and WAIT_FOR_EVENT must be in the same cacheline */
+	if (((sna->kgem.nbatch + 6) >> 4) != (sna->kgem.nbatch + 10) >> 4) {
+		int dw = sna->kgem.nbatch + 6;
+		dw = ALIGN(dw, 16) - dw;
+		while (dw--)
+			*b++ = MI_NOOP;
+	}
+
+	b[0] = MI_LOAD_REGISTER_IMM | 1;
+	b[1] = 0x44050; /* DERRMR */
+	b[2] = ~event;
+	b[3] = MI_LOAD_REGISTER_IMM | 1;
+	b[4] = 0xa188; /* FORCEWAKE_MT */
+	b[5] = 2 << 16 | 2;
+	b[6] = MI_LOAD_REGISTER_IMM | 1;
+	b[7] = 0x70068 + 0x1000 * pipe;
+	b[8] = (1 << 31) | (1 << 30) | (y1 << 16) | y2;
+	b[9] = MI_WAIT_FOR_EVENT | event;
+	b[10] = MI_LOAD_REGISTER_IMM | 1;
+	b[11] = 0xa188; /* FORCEWAKE_MT */
+	b[12] = 2 << 16;
+	b[13] = MI_LOAD_REGISTER_IMM | 1;
+	b[14] = 0x44050; /* DERRMR */
+	b[15] = ~0;
+
+	sna->kgem.nbatch = b - sna->kgem.batch + 16;
+
+	sna->kgem.batch_flags |= I915_EXEC_SECURE;
+	return true;
+}
+
+static bool sna_emit_wait_for_scanline_gen6(struct sna *sna,
+					    xf86CrtcPtr crtc,
+					    int pipe, int y1, int y2,
+					    bool full_height)
+{
+	uint32_t *b;
+	uint32_t event;
+
+	if (!sna->kgem.has_secure_batches)
+		return false;
+
+	assert(y1 >= 0);
+	assert(y2 > y1);
+	assert(sna->kgem.mode == KGEM_RENDER);
+
+	/* Always program one less than the desired value */
+	if (--y1 < 0)
+		y1 = crtc->bounds.y2;
+	y2--;
+
+	/* The scanline granularity is 3 bits */
+	y1 &= ~7;
+	y2 &= ~7;
+	if (y2 == y1)
+		return false;
+
+	event = 1 << (3*full_height + pipe*8);
+
+	b = kgem_get_batch(&sna->kgem);
+	sna->kgem.nbatch += 16;
+
+	b[0] = MI_LOAD_REGISTER_IMM | 1;
+	b[1] = 0x44050; /* DERRMR */
+	b[2] = ~event;
+	b[3] = MI_LOAD_REGISTER_IMM | 1;
+	b[4] = 0x4f100; /* magic */
+	b[5] = (1 << 31) | (1 << 30) | pipe << 29 | (y1 << 16) | y2;
+	b[6] = MI_LOAD_REGISTER_IMM | 1;
+	b[7] = 0x2050; /* PSMI_CTL(rcs) */
+	b[8] = 1 << 16 | 1;
+	b[9] = MI_WAIT_FOR_EVENT | event;
+	b[10] = MI_LOAD_REGISTER_IMM | 1;
+	b[11] = 0x2050; /* PSMI_CTL(rcs) */
+	b[12] = 1 << 16;
+	b[13] = MI_LOAD_REGISTER_IMM | 1;
+	b[14] = 0x44050; /* DERRMR */
+	b[15] = ~0;
+
+	sna->kgem.batch_flags |= I915_EXEC_SECURE;
+	return true;
+}
+
+static bool sna_emit_wait_for_scanline_gen4(struct sna *sna,
+					    xf86CrtcPtr crtc,
+					    int pipe, int y1, int y2,
+					    bool full_height)
+{
+	uint32_t event;
+	uint32_t *b;
+
+	if (pipe == 0) {
+		if (full_height)
+			event = MI_WAIT_FOR_PIPEA_SVBLANK;
+		else
+			event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
+	} else {
+		if (full_height)
+			event = MI_WAIT_FOR_PIPEB_SVBLANK;
+		else
+			event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW;
+	}
+
+	b = kgem_get_batch(&sna->kgem);
+	sna->kgem.nbatch += 5;
+
+	/* The documentation says that the LOAD_SCAN_LINES command
+	 * always comes in pairs. Don't ask me why. */
+	b[2] = b[0] = MI_LOAD_SCAN_LINES_INCL | pipe << 20;
+	b[3] = b[1] = (y1 << 16) | (y2-1);
+	b[4] = MI_WAIT_FOR_EVENT | event;
+
+	return true;
+}
+
+static bool sna_emit_wait_for_scanline_gen2(struct sna *sna,
+					    xf86CrtcPtr crtc,
+					    int pipe, int y1, int y2,
+					    bool full_height)
+{
+	uint32_t *b;
+
+	/*
+	 * Pre-965 doesn't have SVBLANK, so we need a bit
+	 * of extra time for the blitter to start up and
+	 * do its job for a full height blit
+	 */
+	if (full_height)
+		y2 -= 2;
+
+	b = kgem_get_batch(&sna->kgem);
+	sna->kgem.nbatch += 5;
+
+	/* The documentation says that the LOAD_SCAN_LINES command
+	 * always comes in pairs. Don't ask me why. */
+	b[2] = b[0] = MI_LOAD_SCAN_LINES_INCL | pipe << 20;
+	b[3] = b[1] = (y1 << 16) | (y2-1);
+	b[4] = MI_WAIT_FOR_EVENT | 1 << (1 + 4*pipe);
+
+	return true;
+}
+
+bool
+sna_wait_for_scanline(struct sna *sna,
+		      PixmapPtr pixmap,
+		      xf86CrtcPtr crtc,
+		      const BoxRec *clip)
+{
+	bool full_height;
+	int y1, y2, pipe;
+	bool ret;
+
+	assert(crtc != NULL);
+	assert(to_sna_crtc(crtc) != NULL);
+	assert(to_sna_crtc(crtc)->bo != NULL);
+	assert(pixmap == sna->front);
+
+	if (sna->flags & SNA_NO_VSYNC)
+		return false;
+
+	/*
+	 * Make sure we don't wait for a scanline that will
+	 * never occur
+	 */
+	y1 = clip->y1 - crtc->bounds.y1;
+	if (y1 < 0)
+		y1 = 0;
+	y2 = clip->y2 - crtc->bounds.y1;
+	if (y2 > crtc->bounds.y2 - crtc->bounds.y1)
+		y2 = crtc->bounds.y2 - crtc->bounds.y1;
+	DBG(("%s: clipped range = %d, %d\n", __FUNCTION__, y1, y2));
+	if (y2 <= y1 + 4)
+		return false;
+
+	full_height = y1 == 0 && y2 == crtc->bounds.y2 - crtc->bounds.y1;
+
+	if (crtc->mode.Flags & V_INTERLACE) {
+		/* DSL count field lines */
+		y1 /= 2;
+		y2 /= 2;
+	}
+
+	pipe = sna_crtc_pipe(crtc);
+	DBG(("%s: pipe=%d, y1=%d, y2=%d, full_height?=%d\n",
+	     __FUNCTION__, pipe, y1, y2, full_height));
+
+	if (sna->kgem.gen >= 0110)
+		ret = false;
+	else if (sna->kgem.gen == 0101)
+		ret = false; /* chv, vsync method unknown */
+	else if (sna->kgem.gen >= 075)
+		ret = sna_emit_wait_for_scanline_hsw(sna, crtc, pipe, y1, y2, full_height);
+	else if (sna->kgem.gen == 071)
+		ret = false; /* vlv, vsync method unknown */
+	else if (sna->kgem.gen >= 070)
+		ret = sna_emit_wait_for_scanline_ivb(sna, crtc, pipe, y1, y2, full_height);
+	else if (sna->kgem.gen >= 060)
+		ret =sna_emit_wait_for_scanline_gen6(sna, crtc, pipe, y1, y2, full_height);
+	else if (sna->kgem.gen >= 040)
+		ret = sna_emit_wait_for_scanline_gen4(sna, crtc, pipe, y1, y2, full_height);
+	else
+		ret = sna_emit_wait_for_scanline_gen2(sna, crtc, pipe, y1, y2, full_height);
+
+	return ret;
+}
+
+static bool sna_mode_shutdown_crtc(xf86CrtcPtr crtc)
+{
+	struct sna *sna = to_sna(crtc->scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	bool disabled = false;
+	int o;
+
+	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+		   "%s: invalid state found on pipe %d, disabling CRTC:%d\n",
+		   __FUNCTION__,
+		   __sna_crtc_pipe(to_sna_crtc(crtc)),
+		   __sna_crtc_id(to_sna_crtc(crtc)));
+	sna_crtc_disable(crtc, true);
+#if XF86_CRTC_VERSION >= 3
+	crtc->active = FALSE;
+#endif
+	if (crtc->enabled) {
+		crtc->enabled = FALSE;
+		disabled = true;
+	}
+
+	for (o = 0; o < sna->mode.num_real_output; o++) {
+		xf86OutputPtr output = config->output[o];
+
+		if (output->crtc != crtc)
+			continue;
+
+		output->funcs->dpms(output, DPMSModeOff);
+		output->crtc = NULL;
+	}
+
+	return disabled;
+}
+
+static bool
+sna_mode_disable_secondary_planes(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool disabled = false;
+	int c;
+
+	/* Disable all secondary planes on our CRTCs, just in case
+	 * other userspace left garbage in them.
+	 */
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		xf86CrtcPtr crtc = config->crtc[c];
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		struct plane *plane;
+
+		list_for_each_entry(plane, &sna_crtc->sprites, link) {
+			struct local_mode_get_plane p;
+			struct local_mode_set_plane s;
+
+			VG_CLEAR(p);
+			p.plane_id = plane->id;
+			p.count_format_types = 0;
+			if (drmIoctl(sna->kgem.fd,
+				     LOCAL_IOCTL_MODE_GETPLANE,
+				     &p))
+				continue;
+
+			if (p.fb_id == 0 || p.crtc_id == 0)
+				continue;
+
+			memset(&s, 0, sizeof(s));
+			s.plane_id = p.plane_id;
+			s.crtc_id = p.crtc_id;
+			if (drmIoctl(sna->kgem.fd,
+				     LOCAL_IOCTL_MODE_SETPLANE,
+				     &s))
+				disabled |= sna_mode_shutdown_crtc(crtc);
+		}
+	}
+
+	return disabled;
+}
+
+void sna_mode_check(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	bool disabled;
+	int c, o;
+
+	if (sna->flags & SNA_IS_HOSTED)
+		return;
+
+	DBG(("%s: hidden?=%d\n", __FUNCTION__, sna->mode.hidden));
+	if (sna->mode.hidden)
+		return;
+
+	disabled = sna_mode_disable_secondary_planes(sna);
+
+	/* Validate CRTC attachments and force consistency upon the kernel */
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
+		xf86CrtcPtr crtc = config->crtc[c];
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		struct drm_mode_crtc mode;
+		uint32_t expected[2];
+
+		assert(sna_crtc);
+
+#if XF86_CRTC_VERSION >= 3
+		assert(sna_crtc->bo == NULL || crtc->active);
+#endif
+		expected[0] = sna_crtc->bo ? fb_id(sna_crtc->bo) : 0;
+		expected[1] = sna_crtc->flip_bo ? fb_id(sna_crtc->flip_bo) : -1;
+
+		VG_CLEAR(mode);
+		mode.crtc_id = __sna_crtc_id(sna_crtc);
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
+			continue;
+
+		DBG(("%s: crtc=%d, valid?=%d, fb attached?=%d, expected=(%d or %d)\n",
+		     __FUNCTION__,
+		     mode.crtc_id, mode.mode_valid,
+		     mode.fb_id, expected[0], expected[1]));
+
+		if (mode.fb_id != expected[0] && mode.fb_id != expected[1])
+			disabled |= sna_mode_shutdown_crtc(crtc);
+	}
+
+	for (o = 0; o < config->num_output; o++) {
+		xf86OutputPtr output = config->output[o];
+		struct sna_output *sna_output;
+
+		if (output->crtc)
+			continue;
+
+		sna_output = to_sna_output(output);
+		if (sna_output == NULL)
+			continue;
+
+		sna_output->dpms_mode = DPMSModeOff;
+	}
+
+	update_flush_interval(sna);
+
+	if (disabled)
+		xf86RandR12TellChanged(xf86ScrnToScreen(sna->scrn));
+}
+
+static bool
+sna_crtc_hide_planes(struct sna *sna, struct sna_crtc *crtc)
+{
+	struct local_mode_set_plane s;
+	struct plane *plane;
+
+	if (crtc->primary.id == 0)
+		return false;
+
+	memset(&s, 0, sizeof(s));
+	s.plane_id = crtc->primary.id;
+	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
+		return false;
+
+	list_for_each_entry(plane, &crtc->sprites, link) {
+		s.plane_id = plane->id;
+		(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
+	}
+
+	__sna_crtc_disable(sna, crtc);
+	return true;
+}
+
+void sna_mode_reset(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	if (sna->flags & SNA_IS_HOSTED)
+		return;
+
+	DBG(("%s\n", __FUNCTION__));
+
+	sna_disable_cursors(sna->scrn);
+	for (i = 0; i < sna->mode.num_real_crtc; i++)
+		if (!sna_crtc_hide_planes(sna, to_sna_crtc(config->crtc[i])))
+			sna_crtc_disable(config->crtc[i], true);
+	assert(sna->mode.front_active == 0);
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *sna_crtc = to_sna_crtc(config->crtc[i]);
+		struct plane *plane;
+
+		assert(sna_crtc != NULL);
+
+		/* Force the rotation property to be reset on next use */
+		rotation_reset(&sna_crtc->primary);
+		list_for_each_entry(plane, &sna_crtc->sprites, link)
+			rotation_reset(plane);
+	}
+
+	/* VT switching, likely to be fbcon so make the backlight usable */
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		struct sna_output *sna_output = to_sna_output(config->output[i]);
+
+		assert(sna_output != NULL);
+		if (sna_output->dpms_mode != DPMSModeOff)
+			continue;
+
+		if (!sna_output->backlight.iface)
+			continue;
+
+		sna_output_backlight_set(sna_output,
+					 sna_output->backlight_active_level);
+	}
+
+	/* drain the event queue */
+	sna_mode_wakeup(sna);
+}
+
+static void transformed_box(BoxRec *box, xf86CrtcPtr crtc)
+{
+	box->x1 -= crtc->filter_width >> 1;
+	box->x2 += crtc->filter_width >> 1;
+	box->y1 -= crtc->filter_height >> 1;
+	box->y2 += crtc->filter_height >> 1;
+
+	pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, box);
+
+	if (box->x1 < 0)
+		box->x1 = 0;
+	if (box->y1 < 0)
+		box->y1 = 0;
+	if (box->x2 > crtc->mode.HDisplay)
+		box->x2 = crtc->mode.HDisplay;
+	if (box->y2 > crtc->mode.VDisplay)
+		box->y2 = crtc->mode.VDisplay;
+}
+
+inline static DrawablePtr crtc_source(xf86CrtcPtr crtc, int16_t *sx, int16_t *sy)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	if (sna_crtc->slave_pixmap) {
+		DBG(("%s: using slave pixmap=%ld, offset (%d, %d)\n",
+		     __FUNCTION__,
+		     sna_crtc->slave_pixmap->drawable.serialNumber,
+		 -crtc->x, -crtc->y));
+		*sx = -crtc->x;
+		*sy = -crtc->y;
+		return &sna_crtc->slave_pixmap->drawable;
+	} else {
+		DBG(("%s: using Screen pixmap=%ld\n",
+		     __FUNCTION__,
+		     to_sna(crtc->scrn)->front->drawable.serialNumber));
+		*sx = *sy = 0;
+		return &to_sna(crtc->scrn)->front->drawable;
+	}
+}
+
+static void
+sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
+{
+	int16_t sx, sy;
+	struct sna *sna = to_sna(crtc->scrn);
+	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
+	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
+	PictFormatPtr format;
+	PictTransform T;
+	PicturePtr src, dst;
+	PixmapPtr pixmap;
+	int depth, error;
+	void *ptr;
+
+	DBG(("%s: compositing transformed damage boxes, target handle=%d\n", __FUNCTION__, bo->handle));
+
+	error = sna_render_format_for_depth(draw->depth);
+	depth = PIXMAN_FORMAT_DEPTH(error);
+	format = PictureMatchFormat(screen, depth, error);
+	if (format == NULL) {
+		DBG(("%s: can't find format for depth=%d [%08x]\n",
+		     __FUNCTION__, depth, error));
+		return;
+	}
+
+	DBG(("%s: dst format=%08x, depth=%d, bpp=%d, pitch=%d, size=%dx%d\n",
+	     __FUNCTION__, format->format, depth, draw->bitsPerPixel,
+	     bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay));
+
+	if (sx | sy)
+		RegionTranslate(region, sx, sy);
+	error = !sna_drawable_move_region_to_cpu(draw, region, MOVE_READ);
+	if (sx | sy)
+		RegionTranslate(region, -sx, -sy);
+	if (error)
+		return;
+
+	ptr = kgem_bo_map__gtt(&sna->kgem, bo);
+	if (ptr == NULL)
+		return;
+
+	pixmap = sna_pixmap_create_unattached(screen, 0, 0, depth);
+	if (pixmap == NullPixmap)
+		return;
+
+	if (!screen->ModifyPixmapHeader(pixmap,
+					crtc->mode.HDisplay, crtc->mode.VDisplay,
+					depth, draw->bitsPerPixel,
+					bo->pitch, ptr))
+		goto free_pixmap;
+
+	src = CreatePicture(None, draw, format,
+			    0, NULL, serverClient, &error);
+	if (!src)
+		goto free_pixmap;
+
+	pixman_transform_init_translate(&T, sx << 16, sy << 16);
+	pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer);
+	if (!sna_transform_is_integer_translation(&T, &sx, &sy)) {
+#define f2d(x) (((double)(x))/65536.)
+		DBG(("%s: transform=[[%f %f %f], [%f %f %f], [%f %f %f]] (raw [[%x %x %x], [%x %x %x], [%x %x %x]])\n",
+		     __FUNCTION__,
+		     f2d(T.matrix[0][0]),
+		     f2d(T.matrix[0][1]),
+		     f2d(T.matrix[0][2]),
+		     f2d(T.matrix[1][0]),
+		     f2d(T.matrix[1][1]),
+		     f2d(T.matrix[1][2]),
+		     f2d(T.matrix[2][0]),
+		     f2d(T.matrix[2][1]),
+		     f2d(T.matrix[2][2]),
+		     T.matrix[0][0],
+		     T.matrix[0][1],
+		     T.matrix[0][2],
+		     T.matrix[1][0],
+		     T.matrix[1][1],
+		     T.matrix[1][2],
+		     T.matrix[2][0],
+		     T.matrix[2][1],
+		     T.matrix[2][2]));
+#undef f2d
+
+		error = SetPictureTransform(src, &T);
+		if (error)
+			goto free_src;
+		sx = sy = 0;
+	}
+
+	if (crtc->filter && crtc->transform_in_use)
+		SetPicturePictFilter(src, crtc->filter,
+				     crtc->params, crtc->nparams);
+
+	dst = CreatePicture(None, &pixmap->drawable, format,
+			    0, NULL, serverClient, &error);
+	if (!dst)
+		goto free_src;
+
+	kgem_bo_sync__gtt(&sna->kgem, bo);
+
+	if (sigtrap_get() == 0) { /* paranoia */
+		const BoxRec *b = region_rects(region);
+		int n = region_num_rects(region);
+		do {
+			BoxRec box;
+
+			box = *b++;
+			transformed_box(&box, crtc);
+
+			DBG(("%s: (%d, %d)x(%d, %d) -> (%d, %d), (%d, %d)\n",
+			     __FUNCTION__,
+			     b[-1].x1, b[-1].y1, b[-1].x2-b[-1].x1, b[-1].y2-b[-1].y1,
+			     box.x1, box.y1, box.x2, box.y2));
+
+			fbComposite(PictOpSrc, src, NULL, dst,
+				    box.x1 + sx, box.y1 + sy,
+				    0, 0,
+				    box.x1, box.y1,
+				    box.x2 - box.x1, box.y2 - box.y1);
+		} while (--n);
+		sigtrap_put();
+	}
+
+	FreePicture(dst, None);
+free_src:
+	FreePicture(src, None);
+free_pixmap:
+	screen->DestroyPixmap(pixmap);
+}
+
+static void
+sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
+{
+	int16_t sx, sy;
+	struct sna *sna = to_sna(crtc->scrn);
+	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
+	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
+	struct sna_composite_op tmp;
+	PictFormatPtr format;
+	PictTransform T;
+	PicturePtr src, dst;
+	PixmapPtr pixmap;
+	const BoxRec *b;
+	int n, depth, error;
+
+	DBG(("%s: compositing transformed damage boxes\n", __FUNCTION__));
+
+	error = sna_render_format_for_depth(draw->depth);
+	depth = PIXMAN_FORMAT_DEPTH(error);
+	format = PictureMatchFormat(screen, depth, error);
+	if (format == NULL) {
+		DBG(("%s: can't find format for depth=%d [%08x]\n",
+		     __FUNCTION__, depth, error));
+		return;
+	}
+
+	DBG(("%s: dst format=%08x, depth=%d, bpp=%d, pitch=%d, size=%dx%d\n",
+	     __FUNCTION__, format->format, depth, draw->bitsPerPixel,
+	     bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay));
+
+	pixmap = sna_pixmap_create_unattached(screen, 0, 0, depth);
+	if (pixmap == NullPixmap)
+		return;
+
+	if (!screen->ModifyPixmapHeader(pixmap,
+					crtc->mode.HDisplay, crtc->mode.VDisplay,
+					depth, draw->bitsPerPixel,
+					bo->pitch, NULL))
+		goto free_pixmap;
+
+	if (!sna_pixmap_attach_to_bo(pixmap, kgem_bo_reference(bo))) {
+		kgem_bo_destroy(&sna->kgem, bo);
+		goto free_pixmap;
+	}
+
+	src = CreatePicture(None, draw, format,
+			    0, NULL, serverClient, &error);
+	if (!src)
+		goto free_pixmap;
+
+	pixman_transform_init_translate(&T, sx << 16, sy << 16);
+	pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer);
+	if (!sna_transform_is_integer_translation(&T, &sx, &sy)) {
+		error = SetPictureTransform(src, &T);
+		if (error)
+			goto free_src;
+		sx = sy = 0;
+	}
+
+	if (crtc->filter && crtc->transform_in_use)
+		SetPicturePictFilter(src, crtc->filter,
+				     crtc->params, crtc->nparams);
+
+	dst = CreatePicture(None, &pixmap->drawable, format,
+			    0, NULL, serverClient, &error);
+	if (!dst)
+		goto free_src;
+
+	ValidatePicture(src);
+	ValidatePicture(dst);
+
+	/* Composite each box individually as if we are dealing with a rotation
+	 * on a large display, we may have to perform intermediate copies. We
+	 * can then minimise the overdraw by looking at individual boxes rather
+	 * than the bbox.
+	 */
+	n = region_num_rects(region);
+	b = region_rects(region);
+	do {
+		BoxRec box = *b;
+		transformed_box(&box, crtc);
+
+		DBG(("%s: (%d, %d)x(%d, %d) -> (%d, %d), (%d, %d)\n",
+		     __FUNCTION__,
+		     b->x1, b->y1, b->x2-b->x1, b->y2-b->y1,
+		     box.x1, box.y1, box.x2, box.y2));
+
+		if (!sna->render.composite(sna,
+					   PictOpSrc, src, NULL, dst,
+					   sx + box.x1, sy + box.y1,
+					   0, 0,
+					   box.x1, box.y1,
+					   box.x2 - box.x1, box.y2 - box.y1,
+					   0, memset(&tmp, 0, sizeof(tmp)))) {
+			DBG(("%s: unsupported operation!\n", __FUNCTION__));
+			sna_crtc_redisplay__fallback(crtc, region, bo);
+			break;
+		} else {
+			tmp.box(sna, &tmp, &box);
+			tmp.done(sna, &tmp);
+		}
+	} while (b++, --n);
+
+	FreePicture(dst, None);
+free_src:
+	FreePicture(src, None);
+free_pixmap:
+	screen->DestroyPixmap(pixmap);
+}
+
+static void
+sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
+{
+	int16_t tx, ty, sx, sy;
+	struct sna *sna = to_sna(crtc->scrn);
+	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
+	struct sna_pixmap *priv = sna_pixmap((PixmapPtr)draw);
+
+	DBG(("%s: crtc %d [pipe=%d], damage (%d, %d), (%d, %d) x %d\n",
+	     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc),
+	     region->extents.x1, region->extents.y1,
+	     region->extents.x2, region->extents.y2,
+	     region_num_rects(region)));
+
+	if (wedged(sna))
+		goto fallback;
+
+	if (priv->clear) {
+		RegionRec whole;
+
+		DBG(("%s: clear damage boxes\n", __FUNCTION__));
+
+		if (sna_transform_is_integer_translation(&crtc->crtc_to_framebuffer,
+							 &tx, &ty)) {
+			RegionTranslate(region, -tx, -ty);
+		} else {
+			whole.extents = region->extents;
+			whole.data = NULL;
+			transformed_box(&whole.extents, crtc);
+			region = &whole;
+		}
+		if (sna_blt_fill_boxes(sna, GXcopy,
+				       bo, draw->bitsPerPixel,
+				       priv->clear_color,
+				       region_rects(region),
+				       region_num_rects(region)))
+			return;
+	}
+
+	if (crtc->filter == NULL &&
+	    priv->gpu_bo &&
+	    priv->cpu_damage == NULL &&
+	    sna_transform_is_integer_translation(&crtc->crtc_to_framebuffer,
+						 &tx, &ty)) {
+		DrawableRec tmp;
+
+		DBG(("%s: copy damage boxes\n", __FUNCTION__));
+
+		tmp.width = crtc->mode.HDisplay;
+		tmp.height = crtc->mode.VDisplay;
+		tmp.depth = sna->front->drawable.depth;
+		tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+		if (sna->render.copy_boxes(sna, GXcopy,
+					   draw, priv->gpu_bo, sx, sy,
+					   &tmp, bo, -tx, -ty,
+					   region_rects(region), region_num_rects(region), 0))
+			return;
+	}
+
+	if (can_render(sna)) {
+		sna_crtc_redisplay__composite(crtc, region, bo);
+		return;
+	}
+
+fallback:
+	sna_crtc_redisplay__fallback(crtc, region, bo);
+}
+
+static void shadow_flip_handler(struct drm_event_vblank *e,
+				void *data)
+{
+	struct sna *sna = data;
+
+	sna->timer_active |= 1 << FLUSH_TIMER;
+	sna->timer_expire[FLUSH_TIMER] =
+		e->tv_sec * 1000 + e->tv_usec / 1000 +
+		sna->vblank_interval / 2;
+}
+
+void sna_shadow_set_crtc(struct sna *sna,
+			 xf86CrtcPtr crtc,
+			 struct kgem_bo *bo)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	struct sna_pixmap *priv;
+
+	assert(sna_crtc);
+	DBG(("%s: setting shadow override for CRTC:%d to handle=%d\n",
+	     __FUNCTION__, __sna_crtc_id(sna_crtc), bo->handle));
+
+	assert(sna->flags & SNA_TEAR_FREE);
+	assert(!sna_crtc->transform);
+
+	if (sna_crtc->client_bo != bo) {
+		if (sna_crtc->client_bo) {
+			assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
+			sna_crtc->client_bo->active_scanout--;
+			kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
+		}
+
+		sna_crtc->client_bo = kgem_bo_reference(bo);
+		sna_crtc->client_bo->active_scanout++;
+		assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
+		sna_crtc_damage(crtc);
+	}
+
+	list_move(&sna_crtc->shadow_link, &sna->mode.shadow_crtc);
+	sna->mode.shadow_dirty = true;
+
+	priv = sna_pixmap(sna->front);
+	assert(priv->gpu_bo);
+	priv->move_to_gpu = wait_for_shadow;
+	priv->move_to_gpu_data = sna;
+}
+
+void sna_shadow_steal_crtcs(struct sna *sna, struct list *list)
+{
+	list_init(list);
+	while (!list_is_empty(&sna->mode.shadow_crtc)) {
+		RegionRec sub, *damage;
+		struct sna_crtc *crtc =
+			list_first_entry(&sna->mode.shadow_crtc,
+					 struct sna_crtc,
+					 shadow_link);
+
+		damage = DamageRegion(sna->mode.shadow_damage);
+		sub.extents = crtc->base->bounds;
+		sub.data = NULL;
+		RegionSubtract(damage, damage, &sub);
+
+		list_move(&crtc->shadow_link, list);
+	}
+}
+
+void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list)
+{
+	while (!list_is_empty(list)) {
+		struct sna_crtc *crtc =
+			list_first_entry(list,
+					 struct sna_crtc,
+					 shadow_link);
+		assert(crtc->client_bo);
+		sna_shadow_set_crtc(sna, crtc->base, crtc->client_bo);
+	}
+}
+
+void sna_shadow_unset_crtc(struct sna *sna,
+			   xf86CrtcPtr crtc)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+
+	DBG(("%s: clearin shadow override for CRTC:%d\n",
+	     __FUNCTION__, __sna_crtc_id(sna_crtc)));
+
+	if (sna_crtc->client_bo == NULL)
+		return;
+
+	assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
+	sna_crtc->client_bo->active_scanout--;
+	kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
+	sna_crtc->client_bo = NULL;
+	list_del(&sna_crtc->shadow_link);
+	sna->mode.shadow_dirty = true;
+
+	sna_crtc_damage(crtc);
+}
+
+static bool move_crtc_to_gpu(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *crtc = to_sna_crtc(config->crtc[i]);
+		unsigned hint;
+
+		assert(crtc);
+
+		if (crtc->bo == NULL)
+			continue;
+
+		if (crtc->slave_pixmap)
+			continue;
+
+		if (crtc->client_bo)
+			continue;
+
+		if (crtc->shadow_bo)
+			continue;
+
+		hint = MOVE_READ | MOVE_ASYNC_HINT | __MOVE_SCANOUT;
+		if (sna->flags & SNA_TEAR_FREE)
+			hint |= __MOVE_FORCE;
+
+		DBG(("%s: CRTC %d [pipe=%d] requires frontbuffer\n",
+		     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc)));
+		return sna_pixmap_move_to_gpu(sna->front, hint);
+	}
+
+	return true;
+}
+
+void sna_mode_redisplay(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	RegionPtr region;
+	int i;
+
+	if (sna->mode.hidden) {
+		DBG(("%s: hidden outputs, skipping\n", __FUNCTION__));
+		return;
+	}
+
+	if (!sna->mode.shadow_enabled)
+		return;
+
+	assert(sna->mode.shadow_damage);
+
+	DBG(("%s: posting shadow damage? %d (flips pending? %d, mode reconfiguration pending? %d)\n",
+	     __FUNCTION__,
+	     !RegionNil(DamageRegion(sna->mode.shadow_damage)),
+	     sna->mode.flip_active,
+	     sna->mode.dirty));
+	assert((sna->flags & SNA_IS_HOSTED) == 0);
+	assert(sna->mode.shadow_active);
+
+	if (sna->mode.dirty)
+		return;
+
+	if (sna->mode.flip_active) {
+		DBG(("%s: %d outstanding flips\n",
+		     __FUNCTION__, sna->mode.flip_active));
+		return;
+	}
+
+	region = DamageRegion(sna->mode.shadow_damage);
+	if (RegionNil(region))
+		return;
+
+	DBG(("%s: damage: %dx(%d, %d), (%d, %d)\n",
+	     __FUNCTION__, region_num_rects(region),
+	     region->extents.x1, region->extents.y1,
+	     region->extents.x2, region->extents.y2));
+
+	if (!move_crtc_to_gpu(sna)) {
+		DBG(("%s: forcing scanout update using the CPU\n", __FUNCTION__));
+		if (!sna_pixmap_move_to_cpu(sna->front, MOVE_READ))
+			return;
+
+		for (i = 0; i < sna->mode.num_real_crtc; i++) {
+			xf86CrtcPtr crtc = config->crtc[i];
+			struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+			RegionRec damage;
+
+			assert(sna_crtc != NULL);
+			if (!sna_crtc->shadow)
+				continue;
+
+			assert(crtc->enabled);
+			assert(sna_crtc->transform || sna->flags & SNA_TEAR_FREE);
+
+			damage.extents = crtc->bounds;
+			damage.data = NULL;
+			RegionIntersect(&damage, &damage, region);
+			if (!box_empty(&damage.extents)) {
+				DBG(("%s: fallback intersects pipe=%d [(%d, %d), (%d, %d)]\n",
+				     __FUNCTION__, __sna_crtc_pipe(sna_crtc),
+				     damage.extents.x1, damage.extents.y1,
+				     damage.extents.x2, damage.extents.y2));
+
+				sna_crtc_redisplay__fallback(crtc,
+							     &damage,
+							     sna_crtc->bo);
+			}
+			RegionUninit(&damage);
+
+			if (sna_crtc->slave_damage)
+				DamageEmpty(sna_crtc->slave_damage);
+		}
+
+		RegionEmpty(region);
+		return;
+	}
+
+	{
+		struct sna_pixmap *priv;
+
+		priv = sna_pixmap(sna->front);
+		assert(priv != NULL);
+
+		if (priv->move_to_gpu) {
+			if (priv->move_to_gpu == wait_for_shadow &&
+			    !sna->mode.shadow_dirty) {
+				/* No damage written to new scanout
+				 * (backbuffer), ignore redisplay request
+				 * and continue with the current intact
+				 * scanout (frontbuffer).
+				 */
+				DBG(("%s: shadow idle, skipping update\n", __FUNCTION__));
+				RegionEmpty(region);
+				return;
+			}
+
+			(void)priv->move_to_gpu(sna, priv, 0);
+		}
+
+		assert(priv->move_to_gpu == NULL);
+	}
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+		RegionRec damage;
+		int sigio;
+
+		assert(sna_crtc != NULL);
+		DBG(("%s: crtc[%d] transformed? %d\n",
+		     __FUNCTION__, i, sna_crtc->transform));
+
+		if (!sna_crtc->transform)
+			continue;
+
+		assert(crtc->enabled);
+		assert(sna_crtc->bo);
+
+		damage.extents = crtc->bounds;
+		damage.data = NULL;
+
+		RegionIntersect(&damage, &damage, region);
+		DBG(("%s: crtc[%d] damage? %d[%d]: %dx[(%d, %d), (%d, %d)]\n",
+		     __FUNCTION__, i,
+		     !box_empty(&damage.extents), RegionNotEmpty(&damage),
+		     region_num_rects(&damage),
+		     damage.extents.x1, damage.extents.y1,
+		     damage.extents.x2, damage.extents.y2));
+		sigio = sigio_block();
+		if (!box_empty(&damage.extents)) {
+			if (sna->flags & SNA_TEAR_FREE) {
+				RegionRec new_damage;
+				struct drm_mode_crtc_page_flip arg;
+				struct kgem_bo *bo;
+
+				RegionNull(&new_damage);
+				RegionCopy(&new_damage, &damage);
+
+				bo = sna_crtc->cache_bo;
+				if (bo == NULL) {
+					damage.extents = crtc->bounds;
+					damage.data = NULL;
+					bo = kgem_create_2d(&sna->kgem,
+							    crtc->mode.HDisplay,
+							    crtc->mode.VDisplay,
+							    crtc->scrn->bitsPerPixel,
+							    sna_crtc->bo->tiling,
+							    CREATE_SCANOUT);
+					if (bo == NULL)
+						continue;
+				} else
+					RegionUnion(&damage, &damage, &sna_crtc->crtc_damage);
+				sna_crtc->crtc_damage = new_damage;
+
+				sna_crtc_redisplay(crtc, &damage, bo);
+				kgem_bo_submit(&sna->kgem, bo);
+				__kgem_bo_clear_dirty(bo);
+
+				assert_crtc_fb(sna, sna_crtc);
+				arg.crtc_id = __sna_crtc_id(sna_crtc);
+				arg.fb_id = get_fb(sna, bo,
+						   crtc->mode.HDisplay,
+						   crtc->mode.VDisplay);
+				if (arg.fb_id == 0)
+					goto disable1;
+
+				arg.user_data = (uintptr_t)sna_crtc;
+				arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
+				arg.reserved = 0;
+
+				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
+					if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
+						DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
+						     __FUNCTION__, sna_crtc->bo->handle, sna_crtc->bo->active_scanout - 1,
+						     bo->handle, bo->active_scanout));
+						assert(sna_crtc->bo->active_scanout);
+						assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
+						sna_crtc->bo->active_scanout--;
+						kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
+
+						sna_crtc->bo = kgem_bo_reference(bo);
+						sna_crtc->bo->active_scanout++;
+					} else {
+						BoxRec box;
+						DrawableRec tmp;
+
+						DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
+						     __FUNCTION__, arg.fb_id, i, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno));
+						xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+							   "Page flipping failed, disabling TearFree\n");
+						sna->flags &= ~SNA_TEAR_FREE;
+
+disable1:
+						box.x1 = 0;
+						box.y1 = 0;
+						tmp.width = box.x2 = crtc->mode.HDisplay;
+						tmp.height = box.y2 = crtc->mode.VDisplay;
+						tmp.depth = sna->front->drawable.depth;
+						tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+						if (!sna->render.copy_boxes(sna, GXcopy,
+									    &sna->front->drawable, bo, 0, 0,
+									    &tmp, sna_crtc->bo, 0, 0,
+									    &box, 1, COPY_LAST)) {
+							xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+								   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
+								   __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc));
+							sna_crtc_disable(crtc, false);
+						}
+					}
+
+					kgem_bo_destroy(&sna->kgem, bo);
+					sna_crtc->cache_bo = NULL;
+					continue;
+				}
+				sna->mode.flip_active++;
+
+				assert(sna_crtc->flip_bo == NULL);
+				sna_crtc->flip_handler = shadow_flip_handler;
+				sna_crtc->flip_data = sna;
+				sna_crtc->flip_bo = bo;
+				sna_crtc->flip_bo->active_scanout++;
+				sna_crtc->flip_serial = sna_crtc->mode_serial;
+				sna_crtc->flip_pending = true;
+
+				if (sna_crtc->bo != sna->mode.shadow) {
+					assert_scanout(&sna->kgem, sna_crtc->bo,
+						       crtc->mode.HDisplay, crtc->mode.VDisplay);
+					sna_crtc->cache_bo = kgem_bo_reference(sna_crtc->bo);
+				}
+				DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
+				     __FUNCTION__, __sna_crtc_id(sna_crtc), sna_crtc->flip_bo->handle, sna_crtc->flip_bo->active_scanout, sna_crtc->flip_serial));
+			} else {
+				sna_crtc_redisplay(crtc, &damage, sna_crtc->bo);
+				kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
+			}
+		}
+		RegionUninit(&damage);
+		sigio_unblock(sigio);
+
+		if (sna_crtc->slave_damage)
+			DamageEmpty(sna_crtc->slave_damage);
+	}
+
+	if (sna->mode.shadow) {
+		struct kgem_bo *new = __sna_pixmap_get_bo(sna->front);
+		struct kgem_bo *old = sna->mode.shadow;
+		struct drm_mode_crtc_page_flip arg;
+		uint32_t fb = 0;
+		int sigio;
+
+		DBG(("%s: flipping TearFree outputs, current scanout handle=%d [active?=%d], new handle=%d [active=%d]\n",
+		     __FUNCTION__, old->handle, old->active_scanout, new->handle, new->active_scanout));
+
+		assert(new != old);
+		assert(new->refcnt);
+
+		arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
+		arg.reserved = 0;
+
+		kgem_bo_submit(&sna->kgem, new);
+		__kgem_bo_clear_dirty(new);
+
+		sigio = sigio_block();
+		for (i = 0; i < sna->mode.num_real_crtc; i++) {
+			struct sna_crtc *crtc = config->crtc[i]->driver_private;
+			struct kgem_bo *flip_bo;
+			int x, y;
+
+			assert(crtc != NULL);
+			DBG(("%s: crtc %d [%d, pipe=%d] active? %d, transformed? %d\n",
+			     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->bo ? crtc->bo->handle : 0, crtc->transform));
+			if (crtc->bo == NULL || crtc->transform)
+				continue;
+
+			assert(config->crtc[i]->enabled);
+			assert(crtc->flip_bo == NULL);
+			assert_crtc_fb(sna, crtc);
+
+			arg.crtc_id = __sna_crtc_id(crtc);
+			arg.user_data = (uintptr_t)crtc;
+
+			if (crtc->client_bo) {
+				DBG(("%s: apply shadow override bo for CRTC:%d on pipe=%d, handle=%d\n",
+				     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->client_bo->handle));
+				arg.fb_id = get_fb(sna, crtc->client_bo,
+						   crtc->base->mode.HDisplay,
+						   crtc->base->mode.VDisplay);
+				assert(arg.fb_id != fb);
+				flip_bo = crtc->client_bo;
+				x = y = 0;
+			} else {
+				if (fb == 0)
+					fb = get_fb(sna, new, sna->scrn->virtualX, sna->scrn->virtualY);
+				if (fb == 0) {
+fixup_shadow:
+					if (sna_pixmap_move_to_gpu(sna->front, MOVE_READ | MOVE_ASYNC_HINT)) {
+						BoxRec box;
+
+						box.x1 = 0;
+						box.y1 = 0;
+						box.x2 = sna->scrn->virtualX;
+						box.y2 = sna->scrn->virtualY;
+						if (sna->render.copy_boxes(sna, GXcopy,
+									   &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
+									   &sna->front->drawable, old, 0, 0,
+									   &box, 1, COPY_LAST)) {
+							kgem_submit(&sna->kgem);
+							RegionEmpty(region);
+						}
+					}
+
+					sigio_unblock(sigio);
+					return;
+				}
+
+				arg.fb_id = fb;
+				flip_bo = new;
+				x = crtc->base->x;
+				y = crtc->base->y;
+			}
+
+			if (crtc->bo == flip_bo) {
+				assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
+				DBG(("%s: flip handle=%d is already on the CRTC\n",
+				     __FUNCTION__, flip_bo->handle));
+				continue;
+			}
+
+			if (flip_bo->pitch != crtc->bo->pitch || (y << 16 | x)  != crtc->offset) {
+				DBG(("%s: changing pitch (new %d =?= old %d) or offset (new %x =?= old %x)\n",
+				     __FUNCTION__,
+				     flip_bo->pitch, crtc->bo->pitch,
+				     y << 16 | x, crtc->offset));
+fixup_flip:
+				if (sna_crtc_flip(sna, crtc, flip_bo, x, y)) {
+					DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
+					     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout-1,
+					     flip_bo->handle, flip_bo->active_scanout));
+					assert(flip_bo != crtc->bo);
+					assert(crtc->bo->active_scanout);
+					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
+					crtc->bo->active_scanout--;
+					kgem_bo_destroy(&sna->kgem, crtc->bo);
+
+					if (crtc->shadow_bo) {
+						kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+						crtc->shadow_bo = NULL;
+					}
+
+					crtc->bo = kgem_bo_reference(flip_bo);
+					crtc->bo->active_scanout++;
+				} else {
+					if (sna->flags & SNA_TEAR_FREE) {
+						xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+								"Failed to prepare CRTC for page flipping, disabling TearFree\n");
+						sna->flags &= ~SNA_TEAR_FREE;
+					}
+
+					if (sna->mode.flip_active == 0) {
+						DBG(("%s: abandoning flip attempt\n", __FUNCTION__));
+						goto fixup_shadow;
+					}
+
+					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+						   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
+						   __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc));
+					sna_crtc_disable(crtc->base, false);
+				}
+				continue;
+			}
+
+			if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
+				ERR(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
+				     __FUNCTION__, arg.fb_id, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), errno));
+				goto fixup_flip;
+			}
+			sna->mode.flip_active++;
+
+			assert(crtc->flip_bo == NULL);
+			crtc->flip_handler = shadow_flip_handler;
+			crtc->flip_data = sna;
+			crtc->flip_bo = kgem_bo_reference(flip_bo);
+			crtc->flip_bo->active_scanout++;
+			crtc->flip_serial = crtc->mode_serial;
+			crtc->flip_pending = true;
+
+			DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
+			     __FUNCTION__, __sna_crtc_id(crtc), crtc->flip_bo->handle, crtc->flip_bo->active_scanout, crtc->flip_serial));
+
+			{
+				struct drm_i915_gem_busy busy = { .handle = flip_bo->handle, };
+				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy) == 0) {
+					if (busy.busy) {
+						int mode = KGEM_RENDER;
+						if (busy.busy & (0xfffe << 16))
+							mode = KGEM_BLT;
+						DBG(("%s: marking flip bo as busy [%x -> mode=%d]\n", __FUNCTION__, busy.busy, mode));
+						kgem_bo_mark_busy(&sna->kgem, flip_bo, mode);
+					} else
+						__kgem_bo_clear_busy(flip_bo);
+				}
+			}
+		}
+		sigio_unblock(sigio);
+
+		DBG(("%s: flipped %d outputs, shadow active? %d\n",
+		     __FUNCTION__,
+		     sna->mode.flip_active,
+		     sna->mode.shadow ? sna->mode.shadow->handle : 0));
+
+		if (sna->mode.flip_active) {
+			assert(old == sna->mode.shadow);
+			assert(old->refcnt >= 1);
+			set_shadow(sna, region);
+		}
+	} else
+		kgem_submit(&sna->kgem);
+
+	RegionEmpty(region);
+}
+
+int sna_mode_wakeup(struct sna *sna)
+{
+	bool defer_vblanks = sna->mode.flip_active && sna->mode.shadow_enabled;
+	char buffer[1024];
+	int len, i;
+	int ret = 0;
+
+again:
+	/* In order to workaround a kernel bug in not honouring O_NONBLOCK,
+	 * check that the fd is readable before attempting to read the next
+	 * event from drm.
+	 */
+	if (!event_pending(sna->kgem.fd))
+		goto done;
+
+	/* The DRM read semantics guarantees that we always get only
+	 * complete events.
+	 */
+	len = read(sna->kgem.fd, buffer, sizeof (buffer));
+	if (len < (int)sizeof(struct drm_event))
+		goto done;
+
+	/* Note that we cannot rely on the passed in struct sna matching
+	 * the struct sna used for the vblank event (in case it was submitted
+	 * by a different ZaphodHead). When processing the event, we must
+	 * ensure that we only use the pointer passed along with the event.
+	 */
+
+	DBG(("%s: len=%d\n", __FUNCTION__, len));
+
+	i = 0;
+	while (i < len) {
+		struct drm_event *e = (struct drm_event *)&buffer[i];
+		switch (e->type) {
+		case DRM_EVENT_VBLANK:
+			if (defer_vblanks)
+				defer_event(sna, e);
+			else if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
+				sna_present_vblank_handler((struct drm_event_vblank *)e);
+			else
+				sna_dri2_vblank_handler((struct drm_event_vblank *)e);
+			break;
+		case DRM_EVENT_FLIP_COMPLETE:
+			{
+				struct drm_event_vblank *vbl = (struct drm_event_vblank *)e;
+				struct sna_crtc *crtc = (void *)(uintptr_t)vbl->user_data;
+				uint64_t msc;
+
+				/* Beware Zaphod! */
+				sna = to_sna(crtc->base->scrn);
+
+				if (msc64(crtc, vbl->sequence, &msc)) {
+					DBG(("%s: recording last swap on pipe=%d, frame %d [%08llx], time %d.%06d\n",
+					     __FUNCTION__, __sna_crtc_pipe(crtc), vbl->sequence, (long long)msc, vbl->tv_sec, vbl->tv_usec));
+					crtc->swap.tv_sec = vbl->tv_sec;
+					crtc->swap.tv_usec = vbl->tv_usec;
+					crtc->swap.msc = msc;
+				}
+				assert(crtc->flip_pending);
+				crtc->flip_pending = false;
+
+				assert(crtc->flip_bo);
+				assert(crtc->flip_bo->active_scanout);
+				assert(crtc->flip_bo->refcnt >= crtc->flip_bo->active_scanout);
+
+				if (crtc->flip_serial == crtc->mode_serial) {
+					DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
+					     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout - 1,
+					     crtc->flip_bo->handle, crtc->flip_bo->active_scanout));
+					assert(crtc->bo->active_scanout);
+					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
+
+					crtc->bo->active_scanout--;
+					kgem_bo_destroy(&sna->kgem, crtc->bo);
+
+					if (crtc->shadow_bo) {
+						kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+						crtc->shadow_bo = NULL;
+					}
+
+					crtc->bo = crtc->flip_bo;
+					crtc->flip_bo = NULL;
+
+					assert_crtc_fb(sna, crtc);
+				} else {
+					crtc->flip_bo->active_scanout--;
+					kgem_bo_destroy(&sna->kgem, crtc->flip_bo);
+					crtc->flip_bo = NULL;
+				}
+
+				DBG(("%s: flip complete, pending? %d\n", __FUNCTION__, sna->mode.flip_active));
+				assert(sna->mode.flip_active);
+				if (--sna->mode.flip_active == 0) {
+					assert(crtc->flip_handler);
+					crtc->flip_handler(vbl, crtc->flip_data);
+				}
+			}
+			break;
+		default:
+			break;
+		}
+		i += e->length;
+		ret++;
+	}
+
+	goto again;
+
+done:
+	flush_events(sna);
+	return ret;
+}
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src/sna
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new/src
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch/xf86-video-intel-2.99.917.2-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-output-attach-edid-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/create.patch.sh
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/create.patch.sh	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=2.99.917.2
+
+tar --files-from=file.list -xjvf ../xf86-video-intel-$VERSION.tar.bz2
+mv xf86-video-intel-$VERSION xf86-video-intel-$VERSION-orig
+
+cp -rf ./xf86-video-intel-$VERSION-new ./xf86-video-intel-$VERSION
+
+diff --unified -Nr  xf86-video-intel-$VERSION-orig  xf86-video-intel-$VERSION > xf86-video-intel-$VERSION-sna-video-definitions.patch
+
+mv xf86-video-intel-$VERSION-sna-video-definitions.patch ../patches
+
+rm -rf ./xf86-video-intel-$VERSION
+rm -rf ./xf86-video-intel-$VERSION-orig

Property changes on: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/file.list
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/file.list	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xf86-video-intel-2.99.917.2/src/sna/sna_video.h
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna/sna_video.h
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna/sna_video.h	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna/sna_video.h	(revision 5)
@@ -0,0 +1,290 @@
+/***************************************************************************
+
+Copyright 2000 Intel Corporation.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef SNA_VIDEO_H
+#define SNA_VIDEO_H
+
+#include <xf86_OSproc.h>
+#include <xf86xv.h>
+#include <fourcc.h>
+
+#if defined(XvMCExtension) && defined(ENABLE_XVMC)
+#define SNA_XVMC 1
+#endif
+
+#if defined( FOURCC_NV12 )
+#undef FOURCC_NV12
+#endif
+
+#if defined( XVIMAGE_NV12 )
+#undef XVIMAGE_NV12
+#endif
+
+#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X')
+#define FOURCC_RGB565 ((16 << 24) + ('B' << 16) + ('G' << 8) + 'R')
+#define FOURCC_RGB888 ((24 << 24) + ('B' << 16) + ('G' << 8) + 'R')
+#define FOURCC_NV12 (('2' << 24) + ('1' << 16) + ('V' << 8) + 'N')
+#define FOURCC_AYUV (('V' << 24) + ('U' << 16) + ('Y' << 8) + 'A')
+
+/*
+ * Below, a dummy picture type that is used in XvPutImage
+ * only to do an overlay update.
+ * Introduced for the XvMC client lib.
+ * Defined to have a zero data size.
+ */
+#define XVMC_YUV { \
+	FOURCC_XVMC, XvYUV, LSBFirst, \
+	{'X', 'V', 'M', 'C', 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}, \
+	12, XvPlanar, 3, 0, 0, 0, 0, 8, 8, 8, 1, 2, 2, 1, 2, 2, \
+	{'Y', 'V', 'U', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+	XvTopToBottom \
+}
+
+#define XVMC_RGB565 { \
+	FOURCC_RGB565, XvRGB, LSBFirst, \
+	{'P', 'A', 'S', 'S', 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'R', 'G', 'B', '1', '6'}, \
+	16, XvPacked, 1, 16, 0x1f<<11, 0x3f<<5, 0x1f<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	{'B', 'G', 'R', 'X', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+	XvTopToBottom \
+}
+
+#define XVMC_RGB888 { \
+	FOURCC_RGB888, XvRGB, LSBFirst, \
+	{'P', 'A', 'S', 'S', 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'R', 'G', 'B', '2', '4'}, \
+	32, XvPacked, 1, 24, 0xff<<16, 0xff<<8, 0xff<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	{'B', 'G', 'R', 'X', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+	XvTopToBottom \
+}
+
+/* no standard define for this */
+#define XVIMAGE_NV12 { \
+	FOURCC_NV12, XvYUV, LSBFirst,				\
+	{'N','V','1','2', 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+	12, XvPlanar, 2, 0, 0, 0, 0, 8, 8, 8, 1, 2, 2, 1, 2, 2, \
+	{'Y','U','V', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+	XvTopToBottom \
+}
+
+#define XVIMAGE_AYUV { \
+	FOURCC_AYUV, XvYUV, LSBFirst, \
+	{'A', 'Y', 'U', 'V', 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}, \
+	32, XvPacked, 1, 0, 0, 0, 0, 8, 8, 8, 1, 1, 1, 1, 1, 1, \
+	{'A', 'Y', 'U', 'V', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+	XvTopToBottom \
+}
+
+struct sna_video {
+	struct sna *sna;
+
+	int idx; /* XXX expose struct plane instead? */
+
+	int brightness;
+	int contrast;
+	int saturation;
+	xf86CrtcPtr desired_crtc;
+
+	uint32_t gamma0;
+	uint32_t gamma1;
+	uint32_t gamma2;
+	uint32_t gamma3;
+	uint32_t gamma4;
+	uint32_t gamma5;
+
+	unsigned color_key;
+	unsigned color_key_changed;
+	bool has_color_key;
+
+	unsigned colorspace;
+	unsigned colorspace_changed;
+
+	/** YUV data buffers */
+	struct kgem_bo *old_buf[2];
+	struct kgem_bo *buf;
+	int width, height, format;
+
+	int alignment;
+	bool tiled;
+	bool textured;
+
+	struct kgem_bo *bo[4];
+	RegionRec clip;
+
+	int SyncToVblank;	/* -1: auto, 0: off, 1: on */
+	int AlwaysOnTop;
+};
+
+struct sna_video_frame {
+	struct kgem_bo *bo;
+	uint32_t id;
+	uint32_t size;
+	uint32_t UBufOffset;
+	uint32_t VBufOffset;
+	Rotation rotation;
+
+	uint16_t width, height;
+	uint16_t pitch[2];
+
+	/* extents */
+	BoxRec image;
+	BoxRec src;
+};
+
+static inline XvScreenPtr to_xv(ScreenPtr screen)
+{
+	return dixLookupPrivate(&screen->devPrivates, XvGetScreenKey());
+}
+
+void sna_video_init(struct sna *sna, ScreenPtr screen);
+void sna_video_overlay_setup(struct sna *sna, ScreenPtr screen);
+void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen);
+void sna_video_textured_setup(struct sna *sna, ScreenPtr screen);
+void sna_video_destroy_window(WindowPtr win);
+void sna_video_close(struct sna *sna);
+
+XvAdaptorPtr sna_xv_adaptor_alloc(struct sna *sna);
+int sna_xv_fixup_formats(ScreenPtr screen,
+			 XvFormatPtr formats,
+			 int num_formats);
+int sna_xv_alloc_port(unsigned long port, XvPortPtr in, XvPortPtr *out);
+int sna_xv_free_port(XvPortPtr port);
+
+static inline int xvmc_passthrough(int id)
+{
+	switch (id) {
+	case FOURCC_XVMC:
+	case FOURCC_RGB565:
+	case FOURCC_RGB888:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline int is_planar_fourcc(int id)
+{
+	switch (id) {
+	case FOURCC_YV12:
+	case FOURCC_I420:
+	case FOURCC_XVMC:
+	case FOURCC_NV12:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline int is_nv12_fourcc(int id)
+{
+	switch (id) {
+	case FOURCC_NV12:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline int is_ayuv_fourcc(int id)
+{
+	switch (id) {
+	case FOURCC_AYUV:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+bool
+sna_video_clip_helper(struct sna_video *video,
+		      struct sna_video_frame *frame,
+		      xf86CrtcPtr *crtc_ret,
+		      BoxPtr dst,
+		      short src_x, short src_y,
+		      short drw_x, short drw_y,
+		      short src_w, short src_h,
+		      short drw_w, short drw_h,
+		      RegionPtr reg);
+
+void
+sna_video_frame_init(struct sna_video *video,
+		     int id, short width, short height,
+		     struct sna_video_frame *frame);
+
+void
+sna_video_frame_set_rotation(struct sna_video *video,
+			     struct sna_video_frame *frame,
+			     Rotation rotation);
+
+struct kgem_bo *
+sna_video_buffer(struct sna_video *video,
+		 struct sna_video_frame *frame);
+
+bool
+sna_video_copy_data(struct sna_video *video,
+		    struct sna_video_frame *frame,
+		    const uint8_t *buf);
+void
+sna_video_fill_colorkey(struct sna_video *video,
+			const RegionRec *clip);
+
+void sna_video_buffer_fini(struct sna_video *video);
+
+void sna_video_free_buffers(struct sna_video *video);
+
+static inline XvPortPtr
+sna_window_get_port(WindowPtr window)
+{
+	return ((void **)__get_private(window, sna_window_key))[2];
+}
+
+static inline void
+sna_window_set_port(WindowPtr window, XvPortPtr port)
+{
+	((void **)__get_private(window, sna_window_key))[2] = port;
+}
+
+static inline int offset_and_clip(int x, int dx)
+{
+	x += dx;
+	if (x <= 0)
+		return 0;
+	if (x >= MAXSHORT)
+		return MAXSHORT;
+	return x;
+}
+
+static inline void init_video_region(RegionRec *region,
+				     DrawablePtr draw,
+				     int drw_x, int drw_y,
+				     int drw_w, int drw_h)
+{
+	region->extents.x1 = offset_and_clip(draw->x, drw_x);
+	region->extents.y1 = offset_and_clip(draw->y, drw_y);
+	region->extents.x2 = offset_and_clip(draw->x, drw_x + drw_w);
+	region->extents.y2 = offset_and_clip(draw->y, drw_y + drw_h);
+	region->data = NULL;
+}
+
+#endif /* SNA_VIDEO_H */
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src/sna
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new/src
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch/xf86-video-intel-2.99.917.2-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch
===================================================================
--- xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch	(nonexistent)
+++ xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch	(revision 5)

Property changes on: xf86-video-intel/create-2.99.917.2-sna-video-definitions-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel/patches/README
===================================================================
--- xf86-video-intel/patches/README	(nonexistent)
+++ xf86-video-intel/patches/README	(revision 5)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+   TODO: Leave some comment here.
+
+ * end */
Index: xf86-video-intel/patches
===================================================================
--- xf86-video-intel/patches	(nonexistent)
+++ xf86-video-intel/patches	(revision 5)

Property changes on: xf86-video-intel/patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-intel
===================================================================
--- xf86-video-intel	(nonexistent)
+++ xf86-video-intel	(revision 5)

Property changes on: xf86-video-intel
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-mach64/Makefile
===================================================================
--- xf86-video-mach64/Makefile	(nonexistent)
+++ xf86-video-mach64/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-mach64
+
+versions    = 6.9.7
+pkgname     = xf86-video-mach64
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-mach64
===================================================================
--- xf86-video-mach64	(nonexistent)
+++ xf86-video-mach64	(revision 5)

Property changes on: xf86-video-mach64
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-mga/Makefile
===================================================================
--- xf86-video-mga/Makefile	(nonexistent)
+++ xf86-video-mga/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-mga
+
+versions    = 2.0.1
+pkgname     = xf86-video-mga
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-mga
===================================================================
--- xf86-video-mga	(nonexistent)
+++ xf86-video-mga	(revision 5)

Property changes on: xf86-video-mga
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-modesetting/Makefile
===================================================================
--- xf86-video-modesetting/Makefile	(nonexistent)
+++ xf86-video-modesetting/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-modesetting
+
+versions    = 0.9.0
+pkgname     = xf86-video-modesetting
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-modesetting
===================================================================
--- xf86-video-modesetting	(nonexistent)
+++ xf86-video-modesetting	(revision 5)

Property changes on: xf86-video-modesetting
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-neomagic/Makefile
===================================================================
--- xf86-video-neomagic/Makefile	(nonexistent)
+++ xf86-video-neomagic/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-neomagic
+
+versions    = 1.3.0
+pkgname     = xf86-video-neomagic
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-neomagic
===================================================================
--- xf86-video-neomagic	(nonexistent)
+++ xf86-video-neomagic	(revision 5)

Property changes on: xf86-video-neomagic
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-newport/Makefile
===================================================================
--- xf86-video-newport/Makefile	(nonexistent)
+++ xf86-video-newport/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-newport
+
+versions    = 0.2.4
+pkgname     = xf86-video-newport
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-newport
===================================================================
--- xf86-video-newport	(nonexistent)
+++ xf86-video-newport	(revision 5)

Property changes on: xf86-video-newport
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-nouveau/Makefile
===================================================================
--- xf86-video-nouveau/Makefile	(nonexistent)
+++ xf86-video-nouveau/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-nouveau
+
+versions    = 1.0.17
+pkgname     = xf86-video-nouveau
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-nouveau
===================================================================
--- xf86-video-nouveau	(nonexistent)
+++ xf86-video-nouveau	(revision 5)

Property changes on: xf86-video-nouveau
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-nv/Makefile
===================================================================
--- xf86-video-nv/Makefile	(nonexistent)
+++ xf86-video-nv/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-nv
+
+versions    = 2.1.22
+pkgname     = xf86-video-nv
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-nv
===================================================================
--- xf86-video-nv	(nonexistent)
+++ xf86-video-nv	(revision 5)

Property changes on: xf86-video-nv
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-omap/Makefile
===================================================================
--- xf86-video-omap/Makefile	(nonexistent)
+++ xf86-video-omap/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-omap
+
+versions    = 0.4.5
+pkgname     = xf86-video-omap
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-omap
===================================================================
--- xf86-video-omap	(nonexistent)
+++ xf86-video-omap	(revision 5)

Property changes on: xf86-video-omap
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-openchrome/Makefile
===================================================================
--- xf86-video-openchrome/Makefile	(nonexistent)
+++ xf86-video-openchrome/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-openchrome
+
+versions    = 0.6.0
+pkgname     = xf86-video-openchrome
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-openchrome
===================================================================
--- xf86-video-openchrome	(nonexistent)
+++ xf86-video-openchrome	(revision 5)

Property changes on: xf86-video-openchrome
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-r128/Makefile
===================================================================
--- xf86-video-r128/Makefile	(nonexistent)
+++ xf86-video-r128/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-r128
+
+versions    = 6.12.1
+pkgname     = xf86-video-r128
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-r128
===================================================================
--- xf86-video-r128	(nonexistent)
+++ xf86-video-r128	(revision 5)

Property changes on: xf86-video-r128
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-rendition/Makefile
===================================================================
--- xf86-video-rendition/Makefile	(nonexistent)
+++ xf86-video-rendition/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-rendition
+
+versions    = 4.2.7
+pkgname     = xf86-video-rendition
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-rendition
===================================================================
--- xf86-video-rendition	(nonexistent)
+++ xf86-video-rendition	(revision 5)

Property changes on: xf86-video-rendition
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-s3/Makefile
===================================================================
--- xf86-video-s3/Makefile	(nonexistent)
+++ xf86-video-s3/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-s3
+
+versions    = 0.7.0
+pkgname     = xf86-video-s3
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-s3
===================================================================
--- xf86-video-s3	(nonexistent)
+++ xf86-video-s3	(revision 5)

Property changes on: xf86-video-s3
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-s3virge/Makefile
===================================================================
--- xf86-video-s3virge/Makefile	(nonexistent)
+++ xf86-video-s3virge/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-s3virge
+
+versions    = 1.11.0
+pkgname     = xf86-video-s3virge
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-s3virge
===================================================================
--- xf86-video-s3virge	(nonexistent)
+++ xf86-video-s3virge	(revision 5)

Property changes on: xf86-video-s3virge
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-savage/Makefile
===================================================================
--- xf86-video-savage/Makefile	(nonexistent)
+++ xf86-video-savage/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-savage
+
+versions    = 2.3.9
+pkgname     = xf86-video-savage
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-savage
===================================================================
--- xf86-video-savage	(nonexistent)
+++ xf86-video-savage	(revision 5)

Property changes on: xf86-video-savage
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-siliconmotion/Makefile
===================================================================
--- xf86-video-siliconmotion/Makefile	(nonexistent)
+++ xf86-video-siliconmotion/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-siliconmotion
+
+versions    = 1.7.9
+pkgname     = xf86-video-siliconmotion
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-siliconmotion
===================================================================
--- xf86-video-siliconmotion	(nonexistent)
+++ xf86-video-siliconmotion	(revision 5)

Property changes on: xf86-video-siliconmotion
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-sis/Makefile
===================================================================
--- xf86-video-sis/Makefile	(nonexistent)
+++ xf86-video-sis/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-sis
+
+versions    = 0.12.0
+pkgname     = xf86-video-sis
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-sis
===================================================================
--- xf86-video-sis	(nonexistent)
+++ xf86-video-sis	(revision 5)

Property changes on: xf86-video-sis
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-sisusb/Makefile
===================================================================
--- xf86-video-sisusb/Makefile	(nonexistent)
+++ xf86-video-sisusb/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-sisusb
+
+versions    = 0.9.7
+pkgname     = xf86-video-sisusb
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-sisusb
===================================================================
--- xf86-video-sisusb	(nonexistent)
+++ xf86-video-sisusb	(revision 5)

Property changes on: xf86-video-sisusb
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-suncg6/Makefile
===================================================================
--- xf86-video-suncg6/Makefile	(nonexistent)
+++ xf86-video-suncg6/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-suncg6
+
+versions    = 1.1.3
+pkgname     = xf86-video-suncg6
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-suncg6
===================================================================
--- xf86-video-suncg6	(nonexistent)
+++ xf86-video-suncg6	(revision 5)

Property changes on: xf86-video-suncg6
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-sunffb/Makefile
===================================================================
--- xf86-video-sunffb/Makefile	(nonexistent)
+++ xf86-video-sunffb/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-sunffb
+
+versions    = 1.2.3
+pkgname     = xf86-video-sunffb
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-sunffb
===================================================================
--- xf86-video-sunffb	(nonexistent)
+++ xf86-video-sunffb	(revision 5)

Property changes on: xf86-video-sunffb
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-tdfx/Makefile
===================================================================
--- xf86-video-tdfx/Makefile	(nonexistent)
+++ xf86-video-tdfx/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-tdfx
+
+versions    = 1.5.0
+pkgname     = xf86-video-tdfx
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-tdfx
===================================================================
--- xf86-video-tdfx	(nonexistent)
+++ xf86-video-tdfx	(revision 5)

Property changes on: xf86-video-tdfx
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-tga/Makefile
===================================================================
--- xf86-video-tga/Makefile	(nonexistent)
+++ xf86-video-tga/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-tga
+
+versions    = 1.2.2
+pkgname     = xf86-video-tga
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-tga
===================================================================
--- xf86-video-tga	(nonexistent)
+++ xf86-video-tga	(revision 5)

Property changes on: xf86-video-tga
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-trident/Makefile
===================================================================
--- xf86-video-trident/Makefile	(nonexistent)
+++ xf86-video-trident/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-trident
+
+versions    = 1.3.8
+pkgname     = xf86-video-trident
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-trident
===================================================================
--- xf86-video-trident	(nonexistent)
+++ xf86-video-trident	(revision 5)

Property changes on: xf86-video-trident
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-tseng/Makefile
===================================================================
--- xf86-video-tseng/Makefile	(nonexistent)
+++ xf86-video-tseng/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-tseng
+
+versions    = 1.2.5
+pkgname     = xf86-video-tseng
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-tseng
===================================================================
--- xf86-video-tseng	(nonexistent)
+++ xf86-video-tseng	(revision 5)

Property changes on: xf86-video-tseng
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-v4l/Makefile
===================================================================
--- xf86-video-v4l/Makefile	(nonexistent)
+++ xf86-video-v4l/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-v4l
+
+versions    = 0.3.0
+pkgname     = xf86-video-v4l
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-v4l
===================================================================
--- xf86-video-v4l	(nonexistent)
+++ xf86-video-v4l	(revision 5)

Property changes on: xf86-video-v4l
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-vboxvideo/Makefile
===================================================================
--- xf86-video-vboxvideo/Makefile	(nonexistent)
+++ xf86-video-vboxvideo/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-vboxvideo
+
+versions    = 1.0.0
+pkgname     = xf86-video-vboxvideo
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-vboxvideo
===================================================================
--- xf86-video-vboxvideo	(nonexistent)
+++ xf86-video-vboxvideo	(revision 5)

Property changes on: xf86-video-vboxvideo
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-vesa/Makefile
===================================================================
--- xf86-video-vesa/Makefile	(nonexistent)
+++ xf86-video-vesa/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-vesa
+
+versions    = 2.6.0
+pkgname     = xf86-video-vesa
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-vesa
===================================================================
--- xf86-video-vesa	(nonexistent)
+++ xf86-video-vesa	(revision 5)

Property changes on: xf86-video-vesa
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-vmware/Makefile
===================================================================
--- xf86-video-vmware/Makefile	(nonexistent)
+++ xf86-video-vmware/Makefile	(revision 5)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-vmware
+
+versions    = 13.3.0
+pkgname     = xf86-video-vmware
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/xf86-video-vmware-13.0.2-xorg.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-13.0.2-xorg-patch ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: xf86-video-vmware
===================================================================
--- xf86-video-vmware	(nonexistent)
+++ xf86-video-vmware	(revision 5)

Property changes on: xf86-video-vmware
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-voodoo/Makefile
===================================================================
--- xf86-video-voodoo/Makefile	(nonexistent)
+++ xf86-video-voodoo/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-voodoo
+
+versions    = 1.2.6
+pkgname     = xf86-video-voodoo
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-voodoo
===================================================================
--- xf86-video-voodoo	(nonexistent)
+++ xf86-video-voodoo	(revision 5)

Property changes on: xf86-video-voodoo
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-wsfb/Makefile
===================================================================
--- xf86-video-wsfb/Makefile	(nonexistent)
+++ xf86-video-wsfb/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-wsfb
+
+versions    = 0.4.0
+pkgname     = xf86-video-wsfb
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-wsfb
===================================================================
--- xf86-video-wsfb	(nonexistent)
+++ xf86-video-wsfb	(revision 5)

Property changes on: xf86-video-wsfb
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-xgi/Makefile
===================================================================
--- xf86-video-xgi/Makefile	(nonexistent)
+++ xf86-video-xgi/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-xgi
+
+versions    = 1.6.1
+pkgname     = xf86-video-xgi
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-xgi
===================================================================
--- xf86-video-xgi	(nonexistent)
+++ xf86-video-xgi	(revision 5)

Property changes on: xf86-video-xgi
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xf86-video-xgixp/Makefile
===================================================================
--- xf86-video-xgixp/Makefile	(nonexistent)
+++ xf86-video-xgixp/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/driver/xf86-video-xgixp
+
+versions    = 1.8.1
+pkgname     = xf86-video-xgixp
+suffix      = tar.bz2
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xf86-video-xgixp
===================================================================
--- xf86-video-xgixp	(nonexistent)
+++ xf86-video-xgixp	(revision 5)

Property changes on: xf86-video-xgixp
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 5)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~