Blame SOURCES/0002-Add-old-driver-in-as-a-compatibility-layer.patch

28add0
diff -up xf86-video-qxl-20130514/configure.ac.compat xf86-video-qxl-20130514/configure.ac
28add0
--- xf86-video-qxl-20130514/configure.ac.compat	2013-07-03 14:18:40.381914397 +1000
28add0
+++ xf86-video-qxl-20130514/configure.ac	2013-07-03 14:18:57.093319209 +1000
28add0
@@ -155,6 +155,7 @@ AC_CONFIG_FILES([
28add0
                 Makefile
28add0
                 src/Makefile
28add0
                 src/uxa/Makefile
28add0
+		src/compat/Makefile
28add0
                 scripts/Makefile
28add0
                 examples/Makefile
28add0
 ])
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-lookup3.c.compat xf86-video-qxl-20130514/src/compat/compat-lookup3.c
28add0
--- xf86-video-qxl-20130514/src/compat/compat-lookup3.c.compat	2013-07-03 14:18:57.094319233 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-lookup3.c	2013-07-03 14:18:57.094319233 +1000
28add0
@@ -0,0 +1,769 @@
28add0
+/*
28add0
+-------------------------------------------------------------------------------
28add0
+lookup3.c, by Bob Jenkins, May 2006, Public Domain.
28add0
+
28add0
+These are functions for producing 32-bit hashes for hash table lookup.
28add0
+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() 
28add0
+are externally useful functions.  Routines to test the hash are included 
28add0
+if SELF_TEST is defined.  You can use this free for any purpose.  It's in
28add0
+the public domain.  It has no warranty.
28add0
+
28add0
+You probably want to use hashlittle().  hashlittle() and hashbig()
28add0
+hash byte arrays.  hashlittle() is is faster than hashbig() on
28add0
+little-endian machines.  Intel and AMD are little-endian machines.
28add0
+On second thought, you probably want hashlittle2(), which is identical to
28add0
+hashlittle() except it returns two 32-bit hashes for the price of one.  
28add0
+You could implement hashbig2() if you wanted but I haven't bothered here.
28add0
+
28add0
+If you want to find a hash of, say, exactly 7 integers, do
28add0
+  a = i1;  b = i2;  c = i3;
28add0
+  mix(a,b,c);
28add0
+  a += i4; b += i5; c += i6;
28add0
+  mix(a,b,c);
28add0
+  a += i7;
28add0
+  final(a,b,c);
28add0
+then use c as the hash value.  If you have a variable length array of
28add0
+4-byte integers to hash, use hashword().  If you have a byte array (like
28add0
+a character string), use hashlittle().  If you have several byte arrays, or
28add0
+a mix of things, see the comments above hashlittle().  
28add0
+
28add0
+Why is this so big?  I read 12 bytes at a time into 3 4-byte integers, 
28add0
+then mix those integers.  This is fast (you can do a lot more thorough
28add0
+mixing with 12*3 instructions on 3 integers than you can with 3 instructions
28add0
+on 1 byte), but shoehorning those bytes into integers efficiently is messy.
28add0
+-------------------------------------------------------------------------------
28add0
+*/
28add0
+
28add0
+#include <stdio.h>      /* defines printf for tests */
28add0
+#include <time.h>       /* defines time_t for timings in the test */
28add0
+#include "compat-lookup3.h"
28add0
+#ifdef linux
28add0
+# include <endian.h>    /* attempt to define endianness */
28add0
+#endif
28add0
+
28add0
+/*
28add0
+ * My best guess at if you are big-endian or little-endian.  This may
28add0
+ * need adjustment.
28add0
+ */
28add0
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
28add0
+     __BYTE_ORDER == __LITTLE_ENDIAN) || \
28add0
+    (defined(i386) || defined(__i386__) || defined(__i486__) || \
28add0
+     defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
28add0
+# define HASH_LITTLE_ENDIAN 1
28add0
+# define HASH_BIG_ENDIAN 0
28add0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
28add0
+       __BYTE_ORDER == __BIG_ENDIAN) || \
28add0
+      (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
28add0
+# define HASH_LITTLE_ENDIAN 0
28add0
+# define HASH_BIG_ENDIAN 1
28add0
+#else
28add0
+# define HASH_LITTLE_ENDIAN 0
28add0
+# define HASH_BIG_ENDIAN 0
28add0
+#endif
28add0
+
28add0
+#define hashsize(n) ((uint32_t)1<<(n))
28add0
+#define hashmask(n) (hashsize(n)-1)
28add0
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
28add0
+
28add0
+/*
28add0
+-------------------------------------------------------------------------------
28add0
+mix -- mix 3 32-bit values reversibly.
28add0
+
28add0
+This is reversible, so any information in (a,b,c) before mix() is
28add0
+still in (a,b,c) after mix().
28add0
+
28add0
+If four pairs of (a,b,c) inputs are run through mix(), or through
28add0
+mix() in reverse, there are at least 32 bits of the output that
28add0
+are sometimes the same for one pair and different for another pair.
28add0
+This was tested for:
28add0
+* pairs that differed by one bit, by two bits, in any combination
28add0
+  of top bits of (a,b,c), or in any combination of bottom bits of
28add0
+  (a,b,c).
28add0
+* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
28add0
+  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
28add0
+  is commonly produced by subtraction) look like a single 1-bit
28add0
+  difference.
28add0
+* the base values were pseudorandom, all zero but one bit set, or 
28add0
+  all zero plus a counter that starts at zero.
28add0
+
28add0
+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
28add0
+satisfy this are
28add0
+    4  6  8 16 19  4
28add0
+    9 15  3 18 27 15
28add0
+   14  9  3  7 17  3
28add0
+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
28add0
+for "differ" defined as + with a one-bit base and a two-bit delta.  I
28add0
+used http://burtleburtle.net/bob/hash/avalanche.html to choose 
28add0
+the operations, constants, and arrangements of the variables.
28add0
+
28add0
+This does not achieve avalanche.  There are input bits of (a,b,c)
28add0
+that fail to affect some output bits of (a,b,c), especially of a.  The
28add0
+most thoroughly mixed value is c, but it doesn't really even achieve
28add0
+avalanche in c.
28add0
+
28add0
+This allows some parallelism.  Read-after-writes are good at doubling
28add0
+the number of bits affected, so the goal of mixing pulls in the opposite
28add0
+direction as the goal of parallelism.  I did what I could.  Rotates
28add0
+seem to cost as much as shifts on every machine I could lay my hands
28add0
+on, and rotates are much kinder to the top and bottom bits, so I used
28add0
+rotates.
28add0
+-------------------------------------------------------------------------------
28add0
+*/
28add0
+#define mix(a,b,c) \
28add0
+{ \
28add0
+  a -= c;  a ^= rot(c, 4);  c += b; \
28add0
+  b -= a;  b ^= rot(a, 6);  a += c; \
28add0
+  c -= b;  c ^= rot(b, 8);  b += a; \
28add0
+  a -= c;  a ^= rot(c,16);  c += b; \
28add0
+  b -= a;  b ^= rot(a,19);  a += c; \
28add0
+  c -= b;  c ^= rot(b, 4);  b += a; \
28add0
+}
28add0
+
28add0
+/*
28add0
+-------------------------------------------------------------------------------
28add0
+final -- final mixing of 3 32-bit values (a,b,c) into c
28add0
+
28add0
+Pairs of (a,b,c) values differing in only a few bits will usually
28add0
+produce values of c that look totally different.  This was tested for
28add0
+* pairs that differed by one bit, by two bits, in any combination
28add0
+  of top bits of (a,b,c), or in any combination of bottom bits of
28add0
+  (a,b,c).
28add0
+* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
28add0
+  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
28add0
+  is commonly produced by subtraction) look like a single 1-bit
28add0
+  difference.
28add0
+* the base values were pseudorandom, all zero but one bit set, or 
28add0
+  all zero plus a counter that starts at zero.
28add0
+
28add0
+These constants passed:
28add0
+ 14 11 25 16 4 14 24
28add0
+ 12 14 25 16 4 14 24
28add0
+and these came close:
28add0
+  4  8 15 26 3 22 24
28add0
+ 10  8 15 26 3 22 24
28add0
+ 11  8 15 26 3 22 24
28add0
+-------------------------------------------------------------------------------
28add0
+*/
28add0
+#define final(a,b,c) \
28add0
+{ \
28add0
+  c ^= b; c -= rot(b,14); \
28add0
+  a ^= c; a -= rot(c,11); \
28add0
+  b ^= a; b -= rot(a,25); \
28add0
+  c ^= b; c -= rot(b,16); \
28add0
+  a ^= c; a -= rot(c,4);  \
28add0
+  b ^= a; b -= rot(a,14); \
28add0
+  c ^= b; c -= rot(b,24); \
28add0
+}
28add0
+
28add0
+/*
28add0
+--------------------------------------------------------------------
28add0
+ This works on all machines.  To be useful, it requires
28add0
+ -- that the key be an array of uint32_t's, and
28add0
+ -- that the length be the number of uint32_t's in the key
28add0
+
28add0
+ The function hashword() is identical to hashlittle() on little-endian
28add0
+ machines, and identical to hashbig() on big-endian machines,
28add0
+ except that the length has to be measured in uint32_ts rather than in
28add0
+ bytes.  hashlittle() is more complicated than hashword() only because
28add0
+ hashlittle() has to dance around fitting the key bytes into registers.
28add0
+--------------------------------------------------------------------
28add0
+*/
28add0
+uint32_t hashword(
28add0
+    const uint32_t *k,                   /* the key, an array of uint32_t values */
28add0
+    size_t          length,               /* the length of the key, in uint32_ts */
28add0
+    uint32_t        initval)         /* the previous hash, or an arbitrary value */
28add0
+{
28add0
+  uint32_t a,b,c;
28add0
+
28add0
+  /* Set up the internal state */
28add0
+  a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval;
28add0
+
28add0
+  /*------------------------------------------------- handle most of the key */
28add0
+  while (length > 3)
28add0
+  {
28add0
+    a += k[0];
28add0
+    b += k[1];
28add0
+    c += k[2];
28add0
+    mix(a,b,c);
28add0
+    length -= 3;
28add0
+    k += 3;
28add0
+  }
28add0
+
28add0
+  /*------------------------------------------- handle the last 3 uint32_t's */
28add0
+  switch(length)                     /* all the case statements fall through */
28add0
+  { 
28add0
+  case 3 : c+=k[2];
28add0
+  case 2 : b+=k[1];
28add0
+  case 1 : a+=k[0];
28add0
+    final(a,b,c);
28add0
+  case 0:     /* case 0: nothing left to add */
28add0
+    break;
28add0
+  }
28add0
+  /*------------------------------------------------------ report the result */
28add0
+  return c;
28add0
+}
28add0
+
28add0
+
28add0
+/*
28add0
+--------------------------------------------------------------------
28add0
+hashword2() -- same as hashword(), but take two seeds and return two
28add0
+32-bit values.  pc and pb must both be nonnull, and *pc and *pb must
28add0
+both be initialized with seeds.  If you pass in (*pb)==0, the output 
28add0
+(*pc) will be the same as the return value from hashword().
28add0
+--------------------------------------------------------------------
28add0
+*/
28add0
+void hashword2 (
28add0
+const uint32_t *k,                   /* the key, an array of uint32_t values */
28add0
+size_t          length,               /* the length of the key, in uint32_ts */
28add0
+uint32_t       *pc,                      /* IN: seed OUT: primary hash value */
28add0
+uint32_t       *pb)               /* IN: more seed OUT: secondary hash value */
28add0
+{
28add0
+  uint32_t a,b,c;
28add0
+
28add0
+  /* Set up the internal state */
28add0
+  a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc;
28add0
+  c += *pb;
28add0
+
28add0
+  /*------------------------------------------------- handle most of the key */
28add0
+  while (length > 3)
28add0
+  {
28add0
+    a += k[0];
28add0
+    b += k[1];
28add0
+    c += k[2];
28add0
+    mix(a,b,c);
28add0
+    length -= 3;
28add0
+    k += 3;
28add0
+  }
28add0
+
28add0
+  /*------------------------------------------- handle the last 3 uint32_t's */
28add0
+  switch(length)                     /* all the case statements fall through */
28add0
+  { 
28add0
+  case 3 : c+=k[2];
28add0
+  case 2 : b+=k[1];
28add0
+  case 1 : a+=k[0];
28add0
+    final(a,b,c);
28add0
+  case 0:     /* case 0: nothing left to add */
28add0
+    break;
28add0
+  }
28add0
+  /*------------------------------------------------------ report the result */
28add0
+  *pc=c; *pb=b;
28add0
+}
28add0
+
28add0
+
28add0
+/*
28add0
+-------------------------------------------------------------------------------
28add0
+hashlittle() -- hash a variable-length key into a 32-bit value
28add0
+  k       : the key (the unaligned variable-length array of bytes)
28add0
+  length  : the length of the key, counting by bytes
28add0
+  initval : can be any 4-byte value
28add0
+Returns a 32-bit value.  Every bit of the key affects every bit of
28add0
+the return value.  Two keys differing by one or two bits will have
28add0
+totally different hash values.
28add0
+
28add0
+The best hash table sizes are powers of 2.  There is no need to do
28add0
+mod a prime (mod is sooo slow!).  If you need less than 32 bits,
28add0
+use a bitmask.  For example, if you need only 10 bits, do
28add0
+  h = (h & hashmask(10));
28add0
+In which case, the hash table should have hashsize(10) elements.
28add0
+
28add0
+If you are hashing n strings (uint8_t **)k, do it like this:
28add0
+  for (i=0, h=0; i
28add0
+
28add0
+By Bob Jenkins, 2006.  bob_jenkins@burtleburtle.net.  You may use this
28add0
+code any way you wish, private, educational, or commercial.  It's free.
28add0
+
28add0
+Use for hash table lookup, or anything where one collision in 2^^32 is
28add0
+acceptable.  Do NOT use for cryptographic purposes.
28add0
+-------------------------------------------------------------------------------
28add0
+*/
28add0
+
28add0
+uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
28add0
+{
28add0
+  uint32_t a,b,c;                                          /* internal state */
28add0
+  union { const void *ptr; size_t i; } u;     /* needed for Mac Powerbook G4 */
28add0
+
28add0
+  /* Set up the internal state */
28add0
+  a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
28add0
+
28add0
+  u.ptr = key;
28add0
+  if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
28add0
+    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */
28add0
+#ifdef VALGRIND
28add0
+    const uint8_t  *k8;
28add0
+#endif
28add0
+
28add0
+    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0];
28add0
+      b += k[1];
28add0
+      c += k[2];
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 3;
28add0
+    }
28add0
+
28add0
+    /*----------------------------- handle the last (probably partial) block */
28add0
+    /* 
28add0
+     * "k[2]&0xffffff" actually reads beyond the end of the string, but
28add0
+     * then masks off the part it's not allowed to read.  Because the
28add0
+     * string is aligned, the masked-off tail is in the same word as the
28add0
+     * rest of the string.  Every machine with memory protection I've seen
28add0
+     * does it on word boundaries, so is OK with this.  But VALGRIND will
28add0
+     * still catch it and complain.  The masking trick does make the hash
28add0
+     * noticably faster for short strings (like English words).
28add0
+     */
28add0
+#ifndef VALGRIND
28add0
+
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
28add0
+    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
28add0
+    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
28add0
+    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
28add0
+    case 8 : b+=k[1]; a+=k[0]; break;
28add0
+    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
28add0
+    case 6 : b+=k[1]&0xffff; a+=k[0]; break;
28add0
+    case 5 : b+=k[1]&0xff; a+=k[0]; break;
28add0
+    case 4 : a+=k[0]; break;
28add0
+    case 3 : a+=k[0]&0xffffff; break;
28add0
+    case 2 : a+=k[0]&0xffff; break;
28add0
+    case 1 : a+=k[0]&0xff; break;
28add0
+    case 0 : return c;              /* zero length strings require no mixing */
28add0
+    }
28add0
+
28add0
+#else /* make valgrind happy */
28add0
+
28add0
+    k8 = (const uint8_t *)k;
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
28add0
+    case 11: c+=((uint32_t)k8[10])<<16;  /* fall through */
28add0
+    case 10: c+=((uint32_t)k8[9])<<8;    /* fall through */
28add0
+    case 9 : c+=k8[8];                   /* fall through */
28add0
+    case 8 : b+=k[1]; a+=k[0]; break;
28add0
+    case 7 : b+=((uint32_t)k8[6])<<16;   /* fall through */
28add0
+    case 6 : b+=((uint32_t)k8[5])<<8;    /* fall through */
28add0
+    case 5 : b+=k8[4];                   /* fall through */
28add0
+    case 4 : a+=k[0]; break;
28add0
+    case 3 : a+=((uint32_t)k8[2])<<16;   /* fall through */
28add0
+    case 2 : a+=((uint32_t)k8[1])<<8;    /* fall through */
28add0
+    case 1 : a+=k8[0]; break;
28add0
+    case 0 : return c;
28add0
+    }
28add0
+
28add0
+#endif /* !valgrind */
28add0
+
28add0
+  } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
28add0
+    const uint16_t *k = (const uint16_t *)key;         /* read 16-bit chunks */
28add0
+    const uint8_t  *k8;
28add0
+
28add0
+    /*--------------- all but last block: aligned reads and different mixing */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0] + (((uint32_t)k[1])<<16);
28add0
+      b += k[2] + (((uint32_t)k[3])<<16);
28add0
+      c += k[4] + (((uint32_t)k[5])<<16);
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 6;
28add0
+    }
28add0
+
28add0
+    /*----------------------------- handle the last (probably partial) block */
28add0
+    k8 = (const uint8_t *)k;
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[4]+(((uint32_t)k[5])<<16);
28add0
+             b+=k[2]+(((uint32_t)k[3])<<16);
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 11: c+=((uint32_t)k8[10])<<16;     /* fall through */
28add0
+    case 10: c+=k[4];
28add0
+             b+=k[2]+(((uint32_t)k[3])<<16);
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 9 : c+=k8[8];                      /* fall through */
28add0
+    case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 7 : b+=((uint32_t)k8[6])<<16;      /* fall through */
28add0
+    case 6 : b+=k[2];
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 5 : b+=k8[4];                      /* fall through */
28add0
+    case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 3 : a+=((uint32_t)k8[2])<<16;      /* fall through */
28add0
+    case 2 : a+=k[0];
28add0
+             break;
28add0
+    case 1 : a+=k8[0];
28add0
+             break;
28add0
+    case 0 : return c;                     /* zero length requires no mixing */
28add0
+    }
28add0
+
28add0
+  } else {                        /* need to read the key one byte at a time */
28add0
+    const uint8_t *k = (const uint8_t *)key;
28add0
+
28add0
+    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0];
28add0
+      a += ((uint32_t)k[1])<<8;
28add0
+      a += ((uint32_t)k[2])<<16;
28add0
+      a += ((uint32_t)k[3])<<24;
28add0
+      b += k[4];
28add0
+      b += ((uint32_t)k[5])<<8;
28add0
+      b += ((uint32_t)k[6])<<16;
28add0
+      b += ((uint32_t)k[7])<<24;
28add0
+      c += k[8];
28add0
+      c += ((uint32_t)k[9])<<8;
28add0
+      c += ((uint32_t)k[10])<<16;
28add0
+      c += ((uint32_t)k[11])<<24;
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 12;
28add0
+    }
28add0
+
28add0
+    /*-------------------------------- last block: affect all 32 bits of (c) */
28add0
+    switch(length)                   /* all the case statements fall through */
28add0
+    {
28add0
+    case 12: c+=((uint32_t)k[11])<<24;
28add0
+    case 11: c+=((uint32_t)k[10])<<16;
28add0
+    case 10: c+=((uint32_t)k[9])<<8;
28add0
+    case 9 : c+=k[8];
28add0
+    case 8 : b+=((uint32_t)k[7])<<24;
28add0
+    case 7 : b+=((uint32_t)k[6])<<16;
28add0
+    case 6 : b+=((uint32_t)k[5])<<8;
28add0
+    case 5 : b+=k[4];
28add0
+    case 4 : a+=((uint32_t)k[3])<<24;
28add0
+    case 3 : a+=((uint32_t)k[2])<<16;
28add0
+    case 2 : a+=((uint32_t)k[1])<<8;
28add0
+    case 1 : a+=k[0];
28add0
+             break;
28add0
+    case 0 : return c;
28add0
+    }
28add0
+  }
28add0
+
28add0
+  final(a,b,c);
28add0
+  return c;
28add0
+}
28add0
+
28add0
+
28add0
+/*
28add0
+ * hashlittle2: return 2 32-bit hash values
28add0
+ *
28add0
+ * This is identical to hashlittle(), except it returns two 32-bit hash
28add0
+ * values instead of just one.  This is good enough for hash table
28add0
+ * lookup with 2^^64 buckets, or if you want a second hash if you're not
28add0
+ * happy with the first, or if you want a probably-unique 64-bit ID for
28add0
+ * the key.  *pc is better mixed than *pb, so use *pc first.  If you want
28add0
+ * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
28add0
+ */
28add0
+void hashlittle2( 
28add0
+  const void *key,       /* the key to hash */
28add0
+  size_t      length,    /* length of the key */
28add0
+  uint32_t   *pc,        /* IN: primary initval, OUT: primary hash */
28add0
+  uint32_t   *pb)        /* IN: secondary initval, OUT: secondary hash */
28add0
+{
28add0
+  uint32_t a,b,c;                                          /* internal state */
28add0
+  union { const void *ptr; size_t i; } u;     /* needed for Mac Powerbook G4 */
28add0
+
28add0
+  /* Set up the internal state */
28add0
+  a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc;
28add0
+  c += *pb;
28add0
+
28add0
+  u.ptr = key;
28add0
+  if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
28add0
+    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */
28add0
+#ifdef VALGRIND
28add0
+    const uint8_t  *k8;
28add0
+#endif
28add0
+
28add0
+    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0];
28add0
+      b += k[1];
28add0
+      c += k[2];
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 3;
28add0
+    }
28add0
+
28add0
+    /*----------------------------- handle the last (probably partial) block */
28add0
+    /* 
28add0
+     * "k[2]&0xffffff" actually reads beyond the end of the string, but
28add0
+     * then masks off the part it's not allowed to read.  Because the
28add0
+     * string is aligned, the masked-off tail is in the same word as the
28add0
+     * rest of the string.  Every machine with memory protection I've seen
28add0
+     * does it on word boundaries, so is OK with this.  But VALGRIND will
28add0
+     * still catch it and complain.  The masking trick does make the hash
28add0
+     * noticably faster for short strings (like English words).
28add0
+     */
28add0
+#ifndef VALGRIND
28add0
+
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
28add0
+    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
28add0
+    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
28add0
+    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
28add0
+    case 8 : b+=k[1]; a+=k[0]; break;
28add0
+    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
28add0
+    case 6 : b+=k[1]&0xffff; a+=k[0]; break;
28add0
+    case 5 : b+=k[1]&0xff; a+=k[0]; break;
28add0
+    case 4 : a+=k[0]; break;
28add0
+    case 3 : a+=k[0]&0xffffff; break;
28add0
+    case 2 : a+=k[0]&0xffff; break;
28add0
+    case 1 : a+=k[0]&0xff; break;
28add0
+    case 0 : *pc=c; *pb=b; return;  /* zero length strings require no mixing */
28add0
+    }
28add0
+
28add0
+#else /* make valgrind happy */
28add0
+
28add0
+    k8 = (const uint8_t *)k;
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
28add0
+    case 11: c+=((uint32_t)k8[10])<<16;  /* fall through */
28add0
+    case 10: c+=((uint32_t)k8[9])<<8;    /* fall through */
28add0
+    case 9 : c+=k8[8];                   /* fall through */
28add0
+    case 8 : b+=k[1]; a+=k[0]; break;
28add0
+    case 7 : b+=((uint32_t)k8[6])<<16;   /* fall through */
28add0
+    case 6 : b+=((uint32_t)k8[5])<<8;    /* fall through */
28add0
+    case 5 : b+=k8[4];                   /* fall through */
28add0
+    case 4 : a+=k[0]; break;
28add0
+    case 3 : a+=((uint32_t)k8[2])<<16;   /* fall through */
28add0
+    case 2 : a+=((uint32_t)k8[1])<<8;    /* fall through */
28add0
+    case 1 : a+=k8[0]; break;
28add0
+    case 0 : *pc=c; *pb=b; return;  /* zero length strings require no mixing */
28add0
+    }
28add0
+
28add0
+#endif /* !valgrind */
28add0
+
28add0
+  } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
28add0
+    const uint16_t *k = (const uint16_t *)key;         /* read 16-bit chunks */
28add0
+    const uint8_t  *k8;
28add0
+
28add0
+    /*--------------- all but last block: aligned reads and different mixing */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0] + (((uint32_t)k[1])<<16);
28add0
+      b += k[2] + (((uint32_t)k[3])<<16);
28add0
+      c += k[4] + (((uint32_t)k[5])<<16);
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 6;
28add0
+    }
28add0
+
28add0
+    /*----------------------------- handle the last (probably partial) block */
28add0
+    k8 = (const uint8_t *)k;
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[4]+(((uint32_t)k[5])<<16);
28add0
+             b+=k[2]+(((uint32_t)k[3])<<16);
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 11: c+=((uint32_t)k8[10])<<16;     /* fall through */
28add0
+    case 10: c+=k[4];
28add0
+             b+=k[2]+(((uint32_t)k[3])<<16);
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 9 : c+=k8[8];                      /* fall through */
28add0
+    case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 7 : b+=((uint32_t)k8[6])<<16;      /* fall through */
28add0
+    case 6 : b+=k[2];
28add0
+             a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 5 : b+=k8[4];                      /* fall through */
28add0
+    case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
28add0
+             break;
28add0
+    case 3 : a+=((uint32_t)k8[2])<<16;      /* fall through */
28add0
+    case 2 : a+=k[0];
28add0
+             break;
28add0
+    case 1 : a+=k8[0];
28add0
+             break;
28add0
+    case 0 : *pc=c; *pb=b; return;  /* zero length strings require no mixing */
28add0
+    }
28add0
+
28add0
+  } else {                        /* need to read the key one byte at a time */
28add0
+    const uint8_t *k = (const uint8_t *)key;
28add0
+
28add0
+    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0];
28add0
+      a += ((uint32_t)k[1])<<8;
28add0
+      a += ((uint32_t)k[2])<<16;
28add0
+      a += ((uint32_t)k[3])<<24;
28add0
+      b += k[4];
28add0
+      b += ((uint32_t)k[5])<<8;
28add0
+      b += ((uint32_t)k[6])<<16;
28add0
+      b += ((uint32_t)k[7])<<24;
28add0
+      c += k[8];
28add0
+      c += ((uint32_t)k[9])<<8;
28add0
+      c += ((uint32_t)k[10])<<16;
28add0
+      c += ((uint32_t)k[11])<<24;
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 12;
28add0
+    }
28add0
+
28add0
+    /*-------------------------------- last block: affect all 32 bits of (c) */
28add0
+    switch(length)                   /* all the case statements fall through */
28add0
+    {
28add0
+    case 12: c+=((uint32_t)k[11])<<24;
28add0
+    case 11: c+=((uint32_t)k[10])<<16;
28add0
+    case 10: c+=((uint32_t)k[9])<<8;
28add0
+    case 9 : c+=k[8];
28add0
+    case 8 : b+=((uint32_t)k[7])<<24;
28add0
+    case 7 : b+=((uint32_t)k[6])<<16;
28add0
+    case 6 : b+=((uint32_t)k[5])<<8;
28add0
+    case 5 : b+=k[4];
28add0
+    case 4 : a+=((uint32_t)k[3])<<24;
28add0
+    case 3 : a+=((uint32_t)k[2])<<16;
28add0
+    case 2 : a+=((uint32_t)k[1])<<8;
28add0
+    case 1 : a+=k[0];
28add0
+             break;
28add0
+    case 0 : *pc=c; *pb=b; return;  /* zero length strings require no mixing */
28add0
+    }
28add0
+  }
28add0
+
28add0
+  final(a,b,c);
28add0
+  *pc=c; *pb=b;
28add0
+}
28add0
+
28add0
+
28add0
+
28add0
+/*
28add0
+ * hashbig():
28add0
+ * This is the same as hashword() on big-endian machines.  It is different
28add0
+ * from hashlittle() on all machines.  hashbig() takes advantage of
28add0
+ * big-endian byte ordering. 
28add0
+ */
28add0
+uint32_t hashbig( const void *key, size_t length, uint32_t initval)
28add0
+{
28add0
+  uint32_t a,b,c;
28add0
+  union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */
28add0
+
28add0
+  /* Set up the internal state */
28add0
+  a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
28add0
+
28add0
+  u.ptr = key;
28add0
+  if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
28add0
+    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */
28add0
+#ifdef VALGRIND
28add0
+    const uint8_t  *k8;
28add0
+#endif
28add0
+
28add0
+    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += k[0];
28add0
+      b += k[1];
28add0
+      c += k[2];
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 3;
28add0
+    }
28add0
+
28add0
+    /*----------------------------- handle the last (probably partial) block */
28add0
+    /* 
28add0
+     * "k[2]<<8" actually reads beyond the end of the string, but
28add0
+     * then shifts out the part it's not allowed to read.  Because the
28add0
+     * string is aligned, the illegal read is in the same word as the
28add0
+     * rest of the string.  Every machine with memory protection I've seen
28add0
+     * does it on word boundaries, so is OK with this.  But VALGRIND will
28add0
+     * still catch it and complain.  The masking trick does make the hash
28add0
+     * noticably faster for short strings (like English words).
28add0
+     */
28add0
+#ifndef VALGRIND
28add0
+
28add0
+    switch(length)
28add0
+    {
28add0
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
28add0
+    case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
28add0
+    case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
28add0
+    case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
28add0
+    case 8 : b+=k[1]; a+=k[0]; break;
28add0
+    case 7 : b+=k[1]&0xffffff00; a+=k[0]; break;
28add0
+    case 6 : b+=k[1]&0xffff0000; a+=k[0]; break;
28add0
+    case 5 : b+=k[1]&0xff000000; a+=k[0]; break;
28add0
+    case 4 : a+=k[0]; break;
28add0
+    case 3 : a+=k[0]&0xffffff00; break;
28add0
+    case 2 : a+=k[0]&0xffff0000; break;
28add0
+    case 1 : a+=k[0]&0xff000000; break;
28add0
+    case 0 : return c;              /* zero length strings require no mixing */
28add0
+    }
28add0
+
28add0
+#else  /* make valgrind happy */
28add0
+
28add0
+    k8 = (const uint8_t *)k;
28add0
+    switch(length)                   /* all the case statements fall through */
28add0
+    {
28add0
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
28add0
+    case 11: c+=((uint32_t)k8[10])<<8;  /* fall through */
28add0
+    case 10: c+=((uint32_t)k8[9])<<16;  /* fall through */
28add0
+    case 9 : c+=((uint32_t)k8[8])<<24;  /* fall through */
28add0
+    case 8 : b+=k[1]; a+=k[0]; break;
28add0
+    case 7 : b+=((uint32_t)k8[6])<<8;   /* fall through */
28add0
+    case 6 : b+=((uint32_t)k8[5])<<16;  /* fall through */
28add0
+    case 5 : b+=((uint32_t)k8[4])<<24;  /* fall through */
28add0
+    case 4 : a+=k[0]; break;
28add0
+    case 3 : a+=((uint32_t)k8[2])<<8;   /* fall through */
28add0
+    case 2 : a+=((uint32_t)k8[1])<<16;  /* fall through */
28add0
+    case 1 : a+=((uint32_t)k8[0])<<24; break;
28add0
+    case 0 : return c;
28add0
+    }
28add0
+
28add0
+#endif /* !VALGRIND */
28add0
+
28add0
+  } else {                        /* need to read the key one byte at a time */
28add0
+    const uint8_t *k = (const uint8_t *)key;
28add0
+
28add0
+    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
28add0
+    while (length > 12)
28add0
+    {
28add0
+      a += ((uint32_t)k[0])<<24;
28add0
+      a += ((uint32_t)k[1])<<16;
28add0
+      a += ((uint32_t)k[2])<<8;
28add0
+      a += ((uint32_t)k[3]);
28add0
+      b += ((uint32_t)k[4])<<24;
28add0
+      b += ((uint32_t)k[5])<<16;
28add0
+      b += ((uint32_t)k[6])<<8;
28add0
+      b += ((uint32_t)k[7]);
28add0
+      c += ((uint32_t)k[8])<<24;
28add0
+      c += ((uint32_t)k[9])<<16;
28add0
+      c += ((uint32_t)k[10])<<8;
28add0
+      c += ((uint32_t)k[11]);
28add0
+      mix(a,b,c);
28add0
+      length -= 12;
28add0
+      k += 12;
28add0
+    }
28add0
+
28add0
+    /*-------------------------------- last block: affect all 32 bits of (c) */
28add0
+    switch(length)                   /* all the case statements fall through */
28add0
+    {
28add0
+    case 12: c+=k[11];
28add0
+    case 11: c+=((uint32_t)k[10])<<8;
28add0
+    case 10: c+=((uint32_t)k[9])<<16;
28add0
+    case 9 : c+=((uint32_t)k[8])<<24;
28add0
+    case 8 : b+=k[7];
28add0
+    case 7 : b+=((uint32_t)k[6])<<8;
28add0
+    case 6 : b+=((uint32_t)k[5])<<16;
28add0
+    case 5 : b+=((uint32_t)k[4])<<24;
28add0
+    case 4 : a+=k[3];
28add0
+    case 3 : a+=((uint32_t)k[2])<<8;
28add0
+    case 2 : a+=((uint32_t)k[1])<<16;
28add0
+    case 1 : a+=((uint32_t)k[0])<<24;
28add0
+             break;
28add0
+    case 0 : return c;
28add0
+    }
28add0
+  }
28add0
+
28add0
+  final(a,b,c);
28add0
+  return c;
28add0
+}
28add0
+
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-lookup3.h.compat xf86-video-qxl-20130514/src/compat/compat-lookup3.h
28add0
--- xf86-video-qxl-20130514/src/compat/compat-lookup3.h.compat	2013-07-03 14:18:57.094319233 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-lookup3.h	2013-07-03 14:18:57.094319233 +1000
28add0
@@ -0,0 +1,26 @@
28add0
+#ifndef __LOOKUP3_H
28add0
+#define __LOOKUP3_H
28add0
+
28add0
+#if defined(__GNUC__) || defined(__sun)
28add0
+
28add0
+#include <stdint.h>
28add0
+
28add0
+#else
28add0
+
28add0
+#ifdef QXLDD
28add0
+#include <windef.h>
28add0
+#include "os_dep.h"
28add0
+#else
28add0
+#include <stddef.h>
28add0
+#include <basetsd.h>
28add0
+#endif
28add0
+
28add0
+typedef UINT32 uint32_t;
28add0
+typedef UINT16 uint16_t;
28add0
+typedef UINT8 uint8_t;
28add0
+
28add0
+#endif
28add0
+
28add0
+uint32_t hashlittle( const void *key, size_t length, uint32_t initval);
28add0
+
28add0
+#endif
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-qxl_cursor.c.compat xf86-video-qxl-20130514/src/compat/compat-qxl_cursor.c
28add0
--- xf86-video-qxl-20130514/src/compat/compat-qxl_cursor.c.compat	2013-07-03 14:18:57.094319233 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-qxl_cursor.c	2013-07-03 14:18:57.094319233 +1000
28add0
@@ -0,0 +1,196 @@
28add0
+/*
28add0
+ * Copyright 2009 Red Hat, Inc.
28add0
+ *
28add0
+ * Permission is hereby granted, free of charge, to any person obtaining a
28add0
+ * copy of this software and associated documentation files (the "Software"),
28add0
+ * to deal in the Software without restriction, including without limitation
28add0
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
28add0
+ * license, and/or sell copies of the Software, and to permit persons to whom
28add0
+ * the Software is furnished to do so, subject to the following conditions:
28add0
+ *
28add0
+ * The above copyright notice and this permission notice (including the next
28add0
+ * paragraph) shall be included in all copies or substantial portions of the
28add0
+ * Software.
28add0
+ *
28add0
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28add0
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28add0
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
28add0
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
28add0
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28add0
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28add0
+ */
28add0
+
28add0
+#include <string.h>
28add0
+#include "compat-qxl.h"
28add0
+#include <cursorstr.h>
28add0
+
28add0
+static void
28add0
+push_cursor (qxl_screen_t *qxl, struct qxl_cursor_cmd *cursor)
28add0
+{
28add0
+    struct qxl_command cmd;
28add0
+
28add0
+    /* See comment on push_command() in qxl_driver.c */
28add0
+    if (qxl->rom->mode != ~0)
28add0
+    {
28add0
+        cmd.type = QXL_CMD_CURSOR;
28add0
+        cmd.data = physical_address (qxl, cursor);
28add0
+      
28add0
+        qxl_ring_push (qxl->cursor_ring, &cmd);
28add0
+    }
28add0
+}
28add0
+
28add0
+static struct qxl_cursor_cmd *
28add0
+qxl_alloc_cursor_cmd(qxl_screen_t *qxl)
28add0
+{
28add0
+    struct qxl_cursor_cmd *cmd =
28add0
+	qxl_allocnf (qxl, sizeof(struct qxl_cursor_cmd));
28add0
+
28add0
+    cmd->release_info.id = pointer_to_u64 (cmd) | 1;
28add0
+    
28add0
+    return cmd;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_set_cursor_position(ScrnInfoPtr pScrn, int x, int y)
28add0
+{
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    struct qxl_cursor_cmd *cmd = qxl_alloc_cursor_cmd(qxl);
28add0
+
28add0
+    qxl->cur_x = x;
28add0
+    qxl->cur_y = y;
28add0
+    
28add0
+    cmd->type = QXL_CURSOR_MOVE;
28add0
+    cmd->u.position.x = qxl->cur_x + qxl->hot_x;
28add0
+    cmd->u.position.y = qxl->cur_y + qxl->hot_y;
28add0
+
28add0
+    push_cursor(qxl, cmd);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_load_cursor_image(ScrnInfoPtr pScrn, unsigned char *bits)
28add0
+{
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_set_cursor_colors(ScrnInfoPtr pScrn, int bg, int fg)
28add0
+{
28add0
+    /* Should not be called since UseHWCursor returned FALSE */
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs)
28add0
+{
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    int w = pCurs->bits->width;
28add0
+    int h = pCurs->bits->height;
28add0
+    int size = w * h * sizeof (CARD32);
28add0
+
28add0
+    struct qxl_cursor_cmd *cmd = qxl_alloc_cursor_cmd (qxl);
28add0
+    struct qxl_cursor *cursor =
28add0
+	qxl_allocnf(qxl, sizeof(struct qxl_cursor) + size);
28add0
+
28add0
+    cursor->header.unique = 0;
28add0
+    cursor->header.type = CURSOR_TYPE_ALPHA;
28add0
+    cursor->header.width = w;
28add0
+    cursor->header.height = h;
28add0
+    /* I wonder if we can just tell the client that the hotspot is 0, 0
28add0
+     * always? The coordinates we are getting from X are for 0, 0 anyway,
28add0
+     * so the question is if the client uses the hotspot for anything else?
28add0
+     */
28add0
+    cursor->header.hot_spot_x = pCurs->bits->xhot;
28add0
+    cursor->header.hot_spot_y = pCurs->bits->yhot;
28add0
+
28add0
+    cursor->data_size = size;
28add0
+    
28add0
+    cursor->chunk.next_chunk = 0;
28add0
+    cursor->chunk.prev_chunk = 0;
28add0
+    cursor->chunk.data_size = size;
28add0
+
28add0
+    memcpy (cursor->chunk.data, pCurs->bits->argb, size);
28add0
+
28add0
+#if 0
28add0
+    int i, j;
28add0
+    for (j = 0; j < h; ++j)
28add0
+    {
28add0
+	for (i = 0; i < w; ++i)
28add0
+	{
28add0
+	    ErrorF ("%c", (pCurs->bits->argb[j * w + i] & 0xff000000) == 0xff000000? '#' : '.');
28add0
+	}
28add0
+
28add0
+	ErrorF ("\n");
28add0
+    }
28add0
+#endif
28add0
+
28add0
+    qxl->hot_x = pCurs->bits->xhot;
28add0
+    qxl->hot_y = pCurs->bits->yhot;
28add0
+    
28add0
+    cmd->type = QXL_CURSOR_SET;
28add0
+    cmd->u.set.position.x = qxl->cur_x + qxl->hot_x;
28add0
+    cmd->u.set.position.y = qxl->cur_y + qxl->hot_y;
28add0
+    cmd->u.set.shape = physical_address (qxl, cursor);
28add0
+    cmd->u.set.visible = TRUE;
28add0
+
28add0
+    push_cursor(qxl, cmd);
28add0
+}    
28add0
+
28add0
+static Bool
28add0
+qxl_use_hw_cursor (ScreenPtr pScrn, CursorPtr pCurs)
28add0
+{
28add0
+    /* Old-school bitmap cursors are not
28add0
+     * hardware accelerated for now.
28add0
+     */
28add0
+    return FALSE;
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_use_hw_cursorARGB (ScreenPtr pScrn, CursorPtr pCurs)
28add0
+{
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_hide_cursor(ScrnInfoPtr pScrn)
28add0
+{
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    struct qxl_cursor_cmd *cursor = qxl_alloc_cursor_cmd(qxl);
28add0
+
28add0
+    cursor->type = QXL_CURSOR_HIDE;
28add0
+
28add0
+    push_cursor(qxl, cursor);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_show_cursor(ScrnInfoPtr pScrn)
28add0
+{
28add0
+    /*
28add0
+     * slightly hacky, but there's no QXL_CURSOR_SHOW.  Could maybe do
28add0
+     * QXL_CURSOR_SET?
28add0
+     */
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+
28add0
+    qxl_set_cursor_position(pScrn, qxl->cur_x, qxl->cur_y);
28add0
+}
28add0
+
28add0
+hidden void
28add0
+qxl_cursor_init(ScreenPtr pScreen)
28add0
+{
28add0
+    xf86CursorInfoPtr cursor;
28add0
+
28add0
+    cursor = xcalloc(1, sizeof(xf86CursorInfoRec));
28add0
+    if (!cursor)
28add0
+	return;
28add0
+
28add0
+    cursor->MaxWidth = cursor->MaxHeight = 64;
28add0
+    /* cursor->Flags; */
28add0
+    cursor->SetCursorPosition = qxl_set_cursor_position;
28add0
+    cursor->LoadCursorARGB = qxl_load_cursor_argb;
28add0
+    cursor->UseHWCursor = qxl_use_hw_cursor;
28add0
+    cursor->UseHWCursorARGB = qxl_use_hw_cursorARGB;
28add0
+    cursor->LoadCursorImage = qxl_load_cursor_image;
28add0
+    cursor->SetCursorColors = qxl_set_cursor_colors;
28add0
+    cursor->HideCursor = qxl_hide_cursor;
28add0
+    cursor->ShowCursor = qxl_show_cursor;
28add0
+
28add0
+    if (!xf86InitCursor(pScreen, cursor))
28add0
+	xfree(cursor);
28add0
+}
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-qxl_driver.c.compat xf86-video-qxl-20130514/src/compat/compat-qxl_driver.c
28add0
--- xf86-video-qxl-20130514/src/compat/compat-qxl_driver.c.compat	2013-07-03 14:18:57.095319258 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-qxl_driver.c	2013-07-03 14:18:57.095319258 +1000
28add0
@@ -0,0 +1,1454 @@
28add0
+/*
28add0
+ * Copyright 2008 Red Hat, Inc.
28add0
+ *
28add0
+ * Permission is hereby granted, free of charge, to any person obtaining a
28add0
+ * copy of this software and associated documentation files (the "Software"),
28add0
+ * to deal in the Software without restriction, including without limitation
28add0
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
28add0
+ * license, and/or sell copies of the Software, and to permit persons to whom
28add0
+ * the Software is furnished to do so, subject to the following conditions:
28add0
+ *
28add0
+ * The above copyright notice and this permission notice (including the next
28add0
+ * paragraph) shall be included in all copies or substantial portions of the
28add0
+ * Software.
28add0
+ *
28add0
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28add0
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28add0
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
28add0
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
28add0
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28add0
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28add0
+ */
28add0
+
28add0
+/** \file qxl_driver.c
28add0
+ * \author Adam Jackson <ajax@redhat.com>
28add0
+ *
28add0
+ * This is qxl, a driver for the Qumranet paravirtualized graphics device
28add0
+ * in qemu.
28add0
+ */
28add0
+
28add0
+#include <unistd.h>
28add0
+#include <string.h>
28add0
+#include <stdio.h>
28add0
+#include <errno.h>
28add0
+#include <time.h>
28add0
+#include <stdlib.h>
28add0
+#include "compat-qxl.h"
28add0
+#include "assert.h"
28add0
+
28add0
+#define CHECK_POINT()
28add0
+
28add0
+static int
28add0
+garbage_collect (qxl_screen_t *qxl)
28add0
+{
28add0
+    uint64_t id;
28add0
+    int i = 0;
28add0
+    
28add0
+    while (qxl_ring_pop (qxl->release_ring, &id))
28add0
+    {
28add0
+	while (id)
28add0
+	{
28add0
+	    /* We assume that there the two low bits of a pointer are
28add0
+	     * available. If the low one is set, then the command in
28add0
+	     * question is a cursor command
28add0
+	     */
28add0
+#define POINTER_MASK ((1 << 2) - 1)
28add0
+	    
28add0
+	    union qxl_release_info *info = u64_to_pointer (id & ~POINTER_MASK);
28add0
+	    struct qxl_cursor_cmd *cmd = (struct qxl_cursor_cmd *)info;
28add0
+	    struct qxl_drawable *drawable = (struct qxl_drawable *)info;
28add0
+	    int is_cursor = FALSE;
28add0
+
28add0
+	    if ((id & POINTER_MASK) == 1)
28add0
+		is_cursor = TRUE;
28add0
+
28add0
+	    if (is_cursor && cmd->type == QXL_CURSOR_SET)
28add0
+	    {
28add0
+		struct qxl_cursor *cursor = (void *)virtual_address (
28add0
+		    qxl, u64_to_pointer (cmd->u.set.shape));
28add0
+
28add0
+		qxl_free (qxl->mem, cursor);
28add0
+	    }
28add0
+	    else if (!is_cursor && drawable->type == QXL_DRAW_COPY)
28add0
+	    {
28add0
+		struct qxl_image *image = virtual_address (
28add0
+		    qxl, u64_to_pointer (drawable->u.copy.src_bitmap));
28add0
+
28add0
+		qxl_image_destroy (qxl, image);
28add0
+	    }
28add0
+	    
28add0
+	    id = info->next;
28add0
+	    
28add0
+	    qxl_free (qxl->mem, info);
28add0
+	}
28add0
+    }
28add0
+
28add0
+    return i > 0;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_usleep (int useconds)
28add0
+{
28add0
+    struct timespec t;
28add0
+
28add0
+    t.tv_sec = useconds / 1000000;
28add0
+    t.tv_nsec = (useconds - (t.tv_sec * 1000000)) * 1000;
28add0
+
28add0
+    errno = 0;
28add0
+    while (nanosleep (&t, &t) == -1 && errno == EINTR)
28add0
+	;
28add0
+    
28add0
+}
28add0
+
28add0
+#if 0
28add0
+static void
28add0
+push_update_area (qxl_screen_t *qxl, const struct qxl_rect *area)
28add0
+{
28add0
+    struct qxl_update_cmd *update = qxl_allocnf (qxl, sizeof *update);
28add0
+    struct qxl_command cmd;
28add0
+
28add0
+    update->release_info.id = (uint64_t)update;
28add0
+    update->area = *area;
28add0
+    update->update_id = 0;
28add0
+
28add0
+    cmd.type = QXL_CMD_UDPATE;
28add0
+    cmd.data = physical_address (qxl, update);
28add0
+
28add0
+    qxl_ring_push (qxl->command_ring, &cmd);
28add0
+}
28add0
+#endif
28add0
+
28add0
+void *
28add0
+qxl_allocnf (qxl_screen_t *qxl, unsigned long size)
28add0
+{
28add0
+    void *result;
28add0
+    int n_attempts = 0;
28add0
+    static int nth_oom = 1;
28add0
+
28add0
+    garbage_collect (qxl);
28add0
+    
28add0
+    while (!(result = qxl_alloc (qxl->mem, size)))
28add0
+    {
28add0
+	struct qxl_ram_header *ram_header = (void *)((unsigned long)qxl->ram +
28add0
+						     qxl->rom->ram_header_offset);
28add0
+	
28add0
+	/* Rather than go out of memory, we simply tell the
28add0
+	 * device to dump everything
28add0
+	 */
28add0
+	ram_header->update_area.top = 0;
28add0
+	ram_header->update_area.bottom = 1280;
28add0
+	ram_header->update_area.left = 0;
28add0
+	ram_header->update_area.right = 800;
28add0
+	
28add0
+	outb (qxl->io_base + QXL_IO_UPDATE_AREA, 0);
28add0
+	
28add0
+ 	ErrorF ("eliminated memory (%d)\n", nth_oom++);
28add0
+
28add0
+	outb (qxl->io_base + QXL_IO_NOTIFY_OOM, 0);
28add0
+
28add0
+	qxl_usleep (10000);
28add0
+	
28add0
+	if (garbage_collect (qxl))
28add0
+	{
28add0
+	    n_attempts = 0;
28add0
+	}
28add0
+	else if (++n_attempts == 1000)
28add0
+	{
28add0
+	    qxl_mem_dump_stats (qxl->mem, "Out of mem - stats\n");
28add0
+	    
28add0
+	    fprintf (stderr, "Out of memory\n");
28add0
+	    exit (1);
28add0
+	}
28add0
+    }
28add0
+
28add0
+    return result;
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_blank_screen(ScreenPtr pScreen, int mode)
28add0
+{
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_unmap_memory(qxl_screen_t *qxl, int scrnIndex)
28add0
+{
28add0
+#ifdef XSERVER_LIBPCIACCESS
28add0
+    if (qxl->ram)
28add0
+	pci_device_unmap_range(qxl->pci, qxl->ram, qxl->pci->regions[0].size);
28add0
+    if (qxl->vram)
28add0
+	pci_device_unmap_range(qxl->pci, qxl->vram, qxl->pci->regions[1].size);
28add0
+    if (qxl->rom)
28add0
+	pci_device_unmap_range(qxl->pci, qxl->rom, qxl->pci->regions[2].size);
28add0
+#else
28add0
+    if (qxl->ram)
28add0
+	xf86UnMapVidMem(scrnIndex, qxl->ram, (1 << qxl->pci->size[0]));
28add0
+    if (qxl->vram)
28add0
+	xf86UnMapVidMem(scrnIndex, qxl->vram, (1 << qxl->pci->size[1]));
28add0
+    if (qxl->rom)
28add0
+	xf86UnMapVidMem(scrnIndex, qxl->rom, (1 << qxl->pci->size[2]));
28add0
+#endif
28add0
+
28add0
+    qxl->ram = qxl->ram_physical = qxl->vram = qxl->rom = NULL;
28add0
+
28add0
+    qxl->num_modes = 0;
28add0
+    qxl->modes = NULL;
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_map_memory(qxl_screen_t *qxl, int scrnIndex)
28add0
+{
28add0
+#ifdef XSERVER_LIBPCIACCESS
28add0
+    pci_device_map_range(qxl->pci, qxl->pci->regions[0].base_addr, 
28add0
+			 qxl->pci->regions[0].size,
28add0
+			 PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
28add0
+			 &qxl->ram);
28add0
+    qxl->ram_physical = u64_to_pointer (qxl->pci->regions[0].base_addr);
28add0
+
28add0
+    pci_device_map_range(qxl->pci, qxl->pci->regions[1].base_addr, 
28add0
+			 qxl->pci->regions[1].size,
28add0
+			 PCI_DEV_MAP_FLAG_WRITABLE,
28add0
+			 &qxl->vram);
28add0
+
28add0
+    pci_device_map_range(qxl->pci, qxl->pci->regions[2].base_addr, 
28add0
+			 qxl->pci->regions[2].size, 0,
28add0
+			 (void **)&qxl->rom);
28add0
+
28add0
+    qxl->io_base = qxl->pci->regions[3].base_addr;
28add0
+#else
28add0
+    qxl->ram = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
28add0
+			     qxl->pci_tag, qxl->pci->memBase[0],
28add0
+			     (1 << qxl->pci->size[0]));
28add0
+    qxl->ram_physical = (void *)qxl->pci->memBase[0];
28add0
+    
28add0
+    qxl->vram = xf86MapPciMem(scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT,
28add0
+			      qxl->pci_tag, qxl->pci->memBase[1],
28add0
+			      (1 << qxl->pci->size[1]));
28add0
+    
28add0
+    qxl->rom = xf86MapPciMem(scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT,
28add0
+			     qxl->pci_tag, qxl->pci->memBase[2],
28add0
+			     (1 << qxl->pci->size[2]));
28add0
+    
28add0
+    qxl->io_base = qxl->pci->ioBase[3];
28add0
+#endif
28add0
+    if (!qxl->ram || !qxl->vram || !qxl->rom)
28add0
+	return FALSE;
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "ram at %p; vram at %p; rom at %p\n",
28add0
+	       qxl->ram, qxl->vram, qxl->rom);
28add0
+
28add0
+    qxl->num_modes = *(uint32_t *)((uint8_t *)qxl->rom + qxl->rom->modes_offset);
28add0
+    qxl->modes = (struct qxl_mode *)(((uint8_t *)qxl->rom) + qxl->rom->modes_offset + 4);
28add0
+
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_save_state(ScrnInfoPtr pScrn)
28add0
+{
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+
28add0
+    vgaHWSaveFonts(pScrn, &qxl->vgaRegs);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_restore_state(ScrnInfoPtr pScrn)
28add0
+{
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+
28add0
+    vgaHWRestoreFonts(pScrn, &qxl->vgaRegs);
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_close_screen(int scrnIndex, ScreenPtr pScreen)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+
28add0
+    if (pScrn->vtSema) {
28add0
+        qxl_restore_state(pScrn);
28add0
+	qxl_unmap_memory(qxl, scrnIndex);
28add0
+    }
28add0
+    pScrn->vtSema = FALSE;
28add0
+
28add0
+    xfree(qxl->fb);
28add0
+
28add0
+    pScreen->CreateScreenResources = qxl->create_screen_resources;
28add0
+    pScreen->CloseScreen = qxl->close_screen;
28add0
+
28add0
+    return pScreen->CloseScreen(scrnIndex, pScreen);
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
28add0
+{
28add0
+    qxl_screen_t *qxl = xf86Screens[scrnIndex]->driverPrivate;
28add0
+    int mode_index = (int)(unsigned long)p->Private;
28add0
+    struct qxl_mode *m = qxl->modes + mode_index;
28add0
+    ScreenPtr pScreen = qxl->pScrn->pScreen;
28add0
+
28add0
+    if (!m)
28add0
+	return FALSE;
28add0
+
28add0
+    /* if (debug) */
28add0
+    xf86DrvMsg (scrnIndex, X_INFO, "Setting mode %d (%d x %d) (%d x %d) %p\n",
28add0
+		m->id, m->x_res, m->y_res, p->HDisplay, p->VDisplay, p);
28add0
+
28add0
+    outb(qxl->io_base + QXL_IO_RESET, 0);
28add0
+    
28add0
+    outb(qxl->io_base + QXL_IO_SET_MODE, m->id);
28add0
+
28add0
+    qxl->bytes_per_pixel = (qxl->pScrn->bitsPerPixel + 7) / 8;
28add0
+
28add0
+    /* If this happens out of ScreenInit, we won't have a screen yet. In that
28add0
+     * case createScreenResources will make things right.
28add0
+     */
28add0
+    if (pScreen)
28add0
+    {
28add0
+	PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
28add0
+
28add0
+	if (pPixmap)
28add0
+	{
28add0
+	    pScreen->ModifyPixmapHeader(
28add0
+		pPixmap,
28add0
+		m->x_res, m->y_res,
28add0
+		-1, -1,
28add0
+		qxl->pScrn->displayWidth * qxl->bytes_per_pixel,
28add0
+		NULL);
28add0
+	}
28add0
+    }
28add0
+    
28add0
+    if (qxl->mem)
28add0
+    {
28add0
+	qxl_mem_free_all (qxl->mem);
28add0
+	qxl_drop_image_cache (qxl);
28add0
+    }
28add0
+
28add0
+    
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static void
28add0
+push_drawable (qxl_screen_t *qxl, struct qxl_drawable *drawable)
28add0
+{
28add0
+    struct qxl_command cmd;
28add0
+
28add0
+    /* When someone runs "init 3", the device will be 
28add0
+     * switched into VGA mode and there is nothing we
28add0
+     * can do about it. We get no notification.
28add0
+     * 
28add0
+     * However, if commands are submitted when the device
28add0
+     * is in VGA mode, they will be queued up, and then
28add0
+     * the next time a mode set set, an assertion in the
28add0
+     * device will take down the entire virtual machine.
28add0
+     * 
28add0
+     * The author of the QXL device is opposed to this
28add0
+     * for reasons I don't understand.
28add0
+     */
28add0
+    if (qxl->rom->mode != ~0)
28add0
+    {
28add0
+	cmd.type = QXL_CMD_DRAW;
28add0
+	cmd.data = physical_address (qxl, drawable);
28add0
+	    
28add0
+	qxl_ring_push (qxl->command_ring, &cmd);
28add0
+    }
28add0
+}
28add0
+
28add0
+static struct qxl_drawable *
28add0
+make_drawable (qxl_screen_t *qxl, uint8_t type,
28add0
+	       const struct qxl_rect *rect
28add0
+	       /* , pRegion clip */)
28add0
+{
28add0
+    struct qxl_drawable *drawable;
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    drawable = qxl_allocnf (qxl, sizeof *drawable);
28add0
+
28add0
+    CHECK_POINT();
28add0
+
28add0
+    drawable->release_info.id = pointer_to_u64 (drawable);
28add0
+
28add0
+    drawable->type = type;
28add0
+
28add0
+    drawable->effect = QXL_EFFECT_OPAQUE;
28add0
+    drawable->bitmap_offset = 0;
28add0
+    drawable->bitmap_area.top = 0;
28add0
+    drawable->bitmap_area.left = 0;
28add0
+    drawable->bitmap_area.bottom = 0;
28add0
+    drawable->bitmap_area.right = 0;
28add0
+    /* FIXME: add clipping */
28add0
+    drawable->clip.type = QXL_CLIP_TYPE_NONE;
28add0
+
28add0
+    if (rect)
28add0
+	drawable->bbox = *rect;
28add0
+
28add0
+    drawable->mm_time = qxl->rom->mm_clock;
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    return drawable;
28add0
+}
28add0
+
28add0
+enum ROPDescriptor {
28add0
+    ROPD_INVERS_SRC = (1 << 0),
28add0
+    ROPD_INVERS_BRUSH = (1 << 1),
28add0
+    ROPD_INVERS_DEST = (1 << 2),
28add0
+    ROPD_OP_PUT = (1 << 3),
28add0
+    ROPD_OP_OR = (1 << 4),
28add0
+    ROPD_OP_AND = (1 << 5),
28add0
+    ROPD_OP_XOR = (1 << 6),
28add0
+    ROPD_OP_BLACKNESS = (1 << 7),
28add0
+    ROPD_OP_WHITENESS = (1 << 8),
28add0
+    ROPD_OP_INVERS = (1 << 9),
28add0
+    ROPD_INVERS_RES = (1 <<10),
28add0
+};
28add0
+
28add0
+static void
28add0
+undamage_box (qxl_screen_t *qxl, const struct qxl_rect *rect)
28add0
+{
28add0
+    RegionRec region;
28add0
+    BoxRec box;
28add0
+
28add0
+    box.x1 = rect->left;
28add0
+    box.y1 = rect->top;
28add0
+    box.x2 = rect->right;
28add0
+    box.y2 = rect->bottom;
28add0
+
28add0
+    REGION_INIT (qxl->pScrn->pScreen, &region, &box, 0);
28add0
+
28add0
+    REGION_SUBTRACT (qxl->pScrn->pScreen, &(qxl->pending_copy), &(qxl->pending_copy), &region);
28add0
+
28add0
+    REGION_EMPTY (qxl->pScrn->pScreen, &(qxl->pending_copy));
28add0
+}
28add0
+
28add0
+static void
28add0
+clear_pending_damage (qxl_screen_t *qxl)
28add0
+{
28add0
+    REGION_EMPTY (qxl->pScrn->pScreen, &(qxl->pending_copy));
28add0
+}
28add0
+
28add0
+static void
28add0
+submit_fill (qxl_screen_t *qxl, const struct qxl_rect *rect, uint32_t color)
28add0
+{
28add0
+    struct qxl_drawable *drawable;
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    drawable = make_drawable (qxl, QXL_DRAW_FILL, rect);
28add0
+
28add0
+    CHECK_POINT();
28add0
+
28add0
+    drawable->u.fill.brush.type = QXL_BRUSH_TYPE_SOLID;
28add0
+    drawable->u.fill.brush.u.color = color;
28add0
+    drawable->u.fill.rop_descriptor = ROPD_OP_PUT;
28add0
+    drawable->u.fill.mask.flags = 0;
28add0
+    drawable->u.fill.mask.pos.x = 0;
28add0
+    drawable->u.fill.mask.pos.y = 0;
28add0
+    drawable->u.fill.mask.bitmap = 0;
28add0
+
28add0
+    push_drawable (qxl, drawable);
28add0
+
28add0
+    undamage_box (qxl, rect);
28add0
+}
28add0
+
28add0
+static void
28add0
+translate_rect (struct qxl_rect *rect)
28add0
+{
28add0
+    rect->right -= rect->left;
28add0
+    rect->bottom -= rect->top;
28add0
+    rect->left = rect->top = 0;
28add0
+}
28add0
+
28add0
+static void
28add0
+submit_copy (qxl_screen_t *qxl, const struct qxl_rect *rect)
28add0
+{
28add0
+    struct qxl_drawable *drawable;
28add0
+    ScrnInfoPtr pScrn = qxl->pScrn;
28add0
+
28add0
+    if (rect->left == rect->right ||
28add0
+	rect->top == rect->bottom)
28add0
+    {
28add0
+	/* Empty rectangle */
28add0
+	return ;
28add0
+    }
28add0
+    
28add0
+    drawable = make_drawable (qxl, QXL_DRAW_COPY, rect);
28add0
+
28add0
+    drawable->u.copy.src_bitmap = physical_address (
28add0
+	qxl, qxl_image_create (qxl, qxl->fb, rect->left, rect->top,
28add0
+			       rect->right - rect->left,
28add0
+			       rect->bottom - rect->top,
28add0
+			       pScrn->displayWidth * qxl->bytes_per_pixel));
28add0
+    drawable->u.copy.src_area = *rect;
28add0
+    translate_rect (&drawable->u.copy.src_area);
28add0
+    drawable->u.copy.rop_descriptor = ROPD_OP_PUT;
28add0
+    drawable->u.copy.scale_mode = 0;
28add0
+    drawable->u.copy.mask.flags = 0;
28add0
+    drawable->u.copy.mask.pos.x = 0;
28add0
+    drawable->u.copy.mask.pos.y = 0;
28add0
+    drawable->u.copy.mask.bitmap = 0;
28add0
+
28add0
+    push_drawable (qxl, drawable);
28add0
+}
28add0
+
28add0
+static void
28add0
+print_region (const char *header, RegionPtr pRegion)
28add0
+{
28add0
+    int nbox = REGION_NUM_RECTS (pRegion);
28add0
+    BoxPtr pbox = REGION_RECTS (pRegion);
28add0
+
28add0
+    ErrorF ("%s \n", header);
28add0
+    
28add0
+    while (nbox--)
28add0
+    {
28add0
+	ErrorF ("   %d %d %d %d (size: %d %d)\n",
28add0
+		pbox->x1, pbox->y1, pbox->x2, pbox->y2,
28add0
+		pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
28add0
+
28add0
+	pbox++;
28add0
+    }
28add0
+}
28add0
+
28add0
+static void
28add0
+accept_damage (qxl_screen_t *qxl)
28add0
+{
28add0
+    REGION_UNION (qxl->pScrn->pScreen, &(qxl->to_be_sent), &(qxl->to_be_sent), 
28add0
+		  &(qxl->pending_copy));
28add0
+
28add0
+    REGION_EMPTY (qxl->pScrn->pScreen, &(qxl->pending_copy));
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_send_copies (qxl_screen_t *qxl)
28add0
+{
28add0
+    BoxPtr pBox;
28add0
+    int nbox;
28add0
+
28add0
+    nbox = REGION_NUM_RECTS (&qxl->to_be_sent);
28add0
+    pBox = REGION_RECTS (&qxl->to_be_sent);
28add0
+
28add0
+/*      if (REGION_NUM_RECTS (&qxl->to_be_sent) > 0)  */
28add0
+/*        	print_region ("send bits", &qxl->to_be_sent); */
28add0
+    
28add0
+    while (nbox--)
28add0
+    {
28add0
+	struct qxl_rect qrect;
28add0
+
28add0
+	qrect.top = pBox->y1;
28add0
+	qrect.left = pBox->x1;
28add0
+	qrect.bottom = pBox->y2;
28add0
+	qrect.right = pBox->x2;
28add0
+	
28add0
+	submit_copy (qxl, &qrect);
28add0
+
28add0
+	pBox++;
28add0
+    }
28add0
+
28add0
+    REGION_EMPTY(qxl->pScrn->pScreen, &qxl->to_be_sent);
28add0
+}
28add0
+
28add0
+static void
28add0
+paint_shadow (qxl_screen_t *qxl)
28add0
+{
28add0
+    struct qxl_rect qrect;
28add0
+
28add0
+    qrect.top = 0;
28add0
+    qrect.bottom = 1200;
28add0
+    qrect.left = 0;
28add0
+    qrect.right = 1600;
28add0
+
28add0
+    submit_copy (qxl, &qrect);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_sanity_check (qxl_screen_t *qxl)
28add0
+{
28add0
+    /* read the mode back from the rom */
28add0
+    if (!qxl->rom || !qxl->pScrn)
28add0
+	return;
28add0
+
28add0
+    if (qxl->rom->mode == ~0) 
28add0
+    {
28add0
+ 	ErrorF("QXL device jumped back to VGA mode - resetting mode\n");
28add0
+ 	qxl_switch_mode(qxl->pScrn->scrnIndex, qxl->pScrn->currentMode, 0);
28add0
+    }
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_block_handler (pointer data, OSTimePtr pTimeout, pointer pRead)
28add0
+{
28add0
+    qxl_screen_t *qxl = (qxl_screen_t *) data;
28add0
+
28add0
+    if (!qxl->pScrn->vtSema)
28add0
+        return;
28add0
+
28add0
+    qxl_sanity_check(qxl);
28add0
+
28add0
+    accept_damage (qxl);
28add0
+
28add0
+    qxl_send_copies (qxl);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_wakeup_handler (pointer data, int i, pointer LastSelectMask)
28add0
+{
28add0
+}
28add0
+
28add0
+/* Damage Handling
28add0
+ * 
28add0
+ * When something is drawn, X first generates a damage callback, then
28add0
+ * it calls the GC function to actually draw it. In most cases, we want
28add0
+ * to simply draw into the shadow framebuffer, then submit a copy to the
28add0
+ * device, but when the operation is hardware accelerated, we don't want
28add0
+ * to submit the copy. So, damage is first accumulated into 'pending_copy',
28add0
+ * then if we accelerated the operation, that damage is deleted. 
28add0
+ *
28add0
+ * If we _didn't_ accelerate, we need to union the pending_copy damage 
28add0
+ * onto the to_be_sent damage, and then submit a copy command in the block
28add0
+ * handler.
28add0
+ *
28add0
+ * This means that when new damage happens, if there is already pending
28add0
+ * damage, that must first be unioned onto to_be_sent, and then the new
28add0
+ * damage must be stored in pending_copy.
28add0
+ * 
28add0
+ * The qxl_screen_t struct contains two regions, "pending_copy" and 
28add0
+ * "to_be_sent". 
28add0
+ *
28add0
+ * Pending copy is 
28add0
+ * 
28add0
+ */
28add0
+static void
28add0
+qxl_on_damage (DamagePtr pDamage, RegionPtr pRegion, pointer closure)
28add0
+{
28add0
+    qxl_screen_t *qxl = closure;
28add0
+
28add0
+/*     print_region ("damage", pRegion); */
28add0
+    
28add0
+/*     print_region ("on_damage ", pRegion); */
28add0
+
28add0
+    accept_damage (qxl);
28add0
+
28add0
+/*     print_region ("accepting, qxl->to_be_sent is now", &qxl->to_be_sent); */
28add0
+
28add0
+    REGION_COPY (qxl->pScrn->pScreen, &(qxl->pending_copy), pRegion);
28add0
+}
28add0
+
28add0
+
28add0
+static Bool
28add0
+qxl_create_screen_resources(ScreenPtr pScreen)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    Bool ret;
28add0
+    PixmapPtr pPixmap;
28add0
+
28add0
+    pScreen->CreateScreenResources = qxl->create_screen_resources;
28add0
+    ret = pScreen->CreateScreenResources (pScreen);
28add0
+    pScreen->CreateScreenResources = qxl_create_screen_resources;
28add0
+
28add0
+    if (!ret)
28add0
+	return FALSE;
28add0
+
28add0
+    qxl->damage = DamageCreate (qxl_on_damage, NULL,
28add0
+			        DamageReportRawRegion,
28add0
+				TRUE, pScreen, qxl);
28add0
+
28add0
+
28add0
+    pPixmap = pScreen->GetScreenPixmap(pScreen);
28add0
+
28add0
+    if (!RegisterBlockAndWakeupHandlers(qxl_block_handler, qxl_wakeup_handler, qxl))
28add0
+	return FALSE;
28add0
+
28add0
+    REGION_INIT (pScreen, &(qxl->pending_copy), NullBox, 0);
28add0
+
28add0
+    REGION_INIT (pScreen, &(qxl->to_be_sent), NullBox, 0);
28add0
+ 
28add0
+    DamageRegister (&pPixmap->drawable, qxl->damage);
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static PixmapPtr 
28add0
+get_window_pixmap (DrawablePtr pDrawable, int *xoff, int *yoff)
28add0
+{
28add0
+    ScreenPtr pScreen = pDrawable->pScreen;
28add0
+    PixmapPtr result;
28add0
+
28add0
+    if (pDrawable->type != DRAWABLE_WINDOW)
28add0
+	return NULL;
28add0
+
28add0
+    result = pScreen->GetWindowPixmap ((WindowPtr)pDrawable);
28add0
+
28add0
+    *xoff = pDrawable->x;
28add0
+    *yoff = pDrawable->y;
28add0
+
28add0
+    return result;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_poly_fill_rect (DrawablePtr pDrawable,
28add0
+		 GCPtr	     pGC,
28add0
+		 int	     nrect,
28add0
+		 xRectangle *prect)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[pDrawable->pScreen->myNum];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    PixmapPtr pPixmap;
28add0
+    int xoff, yoff;
28add0
+
28add0
+    if ((pPixmap = get_window_pixmap (pDrawable, &xoff, &yoff))	&&
28add0
+	pGC->fillStyle == FillSolid				&&
28add0
+	pGC->alu == GXcopy					&&
28add0
+	(unsigned int)pGC->planemask == FB_ALLONES)
28add0
+    {
28add0
+	RegionPtr pReg = RECTS_TO_REGION (pScreen, nrect, prect, CT_UNSORTED);
28add0
+	RegionPtr pClip = fbGetCompositeClip (pGC);
28add0
+	BoxPtr pBox;
28add0
+	int nbox;
28add0
+	
28add0
+	REGION_TRANSLATE(pScreen, pReg, xoff, yoff);
28add0
+	REGION_INTERSECT(pScreen, pReg, pClip, pReg);
28add0
+
28add0
+	pBox = REGION_RECTS (pReg);
28add0
+	nbox = REGION_NUM_RECTS (pReg);
28add0
+
28add0
+	while (nbox--)
28add0
+	{
28add0
+	    struct qxl_rect qrect;
28add0
+
28add0
+	    qrect.left = pBox->x1;
28add0
+	    qrect.right = pBox->x2;
28add0
+	    qrect.top = pBox->y1;
28add0
+	    qrect.bottom = pBox->y2;
28add0
+
28add0
+	    submit_fill (qxl, &qrect, pGC->fgPixel);
28add0
+
28add0
+	    pBox++;
28add0
+	}
28add0
+
28add0
+	REGION_DESTROY (pScreen, pReg);
28add0
+    }
28add0
+    
28add0
+    fbPolyFillRect (pDrawable, pGC, nrect, prect);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_copy_n_to_n (DrawablePtr    pSrcDrawable,
28add0
+		 DrawablePtr    pDstDrawable,
28add0
+		 GCPtr	        pGC,
28add0
+		 BoxPtr	        pbox,
28add0
+		 int	        nbox,
28add0
+		 int	        dx,
28add0
+		 int	        dy,
28add0
+		 Bool	        reverse,
28add0
+		 Bool	        upsidedown,
28add0
+		 Pixel	        bitplane,
28add0
+		 void	       *closure)
28add0
+{
28add0
+    ScreenPtr pScreen = pSrcDrawable->pScreen;
28add0
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    int src_xoff, src_yoff;
28add0
+    int dst_xoff, dst_yoff;
28add0
+    PixmapPtr pSrcPixmap, pDstPixmap;
28add0
+
28add0
+    if ((pSrcPixmap = get_window_pixmap (pSrcDrawable, &src_xoff, &src_yoff)) &&
28add0
+	(pDstPixmap = get_window_pixmap (pDstDrawable, &dst_xoff, &dst_yoff)))
28add0
+    {
28add0
+	int n = nbox;
28add0
+	BoxPtr b = pbox;
28add0
+	
28add0
+	assert (pSrcPixmap == pDstPixmap);
28add0
+
28add0
+/* 	ErrorF ("Accelerated copy: %d boxes\n", n); */
28add0
+
28add0
+	/* At this point we know that any pending damage must
28add0
+	 * have been caused by whatever copy operation triggered us.
28add0
+	 * 
28add0
+	 * Therefore we can clear it.
28add0
+	 *
28add0
+	 * We couldn't clear it at the toplevel function because 
28add0
+	 * the copy might end up being empty, in which case no
28add0
+	 * damage would have been generated. Which means the
28add0
+	 * pending damage would have been caused by some
28add0
+	 * earlier operation.
28add0
+	 */
28add0
+	if (n)
28add0
+	{
28add0
+/* 	    ErrorF ("Clearing pending damage\n"); */
28add0
+	    clear_pending_damage (qxl);
28add0
+	    
28add0
+	    /* We have to do this because the copy will cause the damage
28add0
+	     * to be sent to move.
28add0
+	     * 
28add0
+	     * Instead of just sending the bits, we could also move
28add0
+	     * the existing damage around; however that's a bit more 
28add0
+	     * complex, and the performance win is unlikely to be
28add0
+	     * very big.
28add0
+	     */
28add0
+	    qxl_send_copies (qxl);
28add0
+	}
28add0
+    
28add0
+	while (n--)
28add0
+	{
28add0
+	    struct qxl_drawable *drawable;
28add0
+	    struct qxl_rect qrect;
28add0
+	    
28add0
+	    qrect.top = b->y1;
28add0
+	    qrect.bottom = b->y2;
28add0
+	    qrect.left = b->x1;
28add0
+	    qrect.right = b->x2;
28add0
+
28add0
+/* 	    ErrorF ("   Translate %d %d %d %d by %d %d (offsets %d %d)\n", */
28add0
+/* 		    b->x1, b->y1, b->x2, b->y2, */
28add0
+/* 		    dx, dy, dst_xoff, dst_yoff); */
28add0
+	    
28add0
+	    drawable = make_drawable (qxl, QXL_COPY_BITS, &qrect);
28add0
+	    drawable->u.copy_bits.src_pos.x = b->x1 + dx;
28add0
+	    drawable->u.copy_bits.src_pos.y = b->y1 + dy;
28add0
+
28add0
+	    push_drawable (qxl, drawable);
28add0
+
28add0
+#if 0
28add0
+	    if (closure)
28add0
+		qxl_usleep (1000000);
28add0
+#endif
28add0
+	    
28add0
+#if 0
28add0
+	    submit_fill (qxl, &qrect, rand());
28add0
+#endif
28add0
+
28add0
+	    b++;
28add0
+	}
28add0
+    }
28add0
+/*     else */
28add0
+/* 	ErrorF ("Unaccelerated copy\n"); */
28add0
+
28add0
+    fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
28add0
+}
28add0
+
28add0
+static RegionPtr
28add0
+qxl_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
28add0
+	    int srcx, int srcy, int width, int height, int dstx, int dsty)
28add0
+{
28add0
+    if (pSrcDrawable->type == DRAWABLE_WINDOW &&
28add0
+	pDstDrawable->type == DRAWABLE_WINDOW)
28add0
+    {
28add0
+	RegionPtr res;
28add0
+
28add0
+/* 	ErrorF ("accelerated copy %d %d %d %d %d %d\n",  */
28add0
+/* 		srcx, srcy, width, height, dstx, dsty); */
28add0
+
28add0
+	res = fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
28add0
+			srcx, srcy, width, height, dstx, dsty,
28add0
+			qxl_copy_n_to_n, 0, NULL);
28add0
+
28add0
+	return res;
28add0
+    }
28add0
+    else
28add0
+    {
28add0
+/* 	ErrorF ("Falling back %d %d %d %d %d %d\n",  */
28add0
+/* 		srcx, srcy, width, height, dstx, dsty); */
28add0
+
28add0
+	return fbCopyArea (pSrcDrawable, pDstDrawable, pGC,
28add0
+			   srcx, srcy, width, height, dstx, dsty);
28add0
+    }
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_fill_region_solid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel)
28add0
+{
28add0
+    ScreenPtr pScreen = pDrawable->pScreen;
28add0
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    PixmapPtr pPixmap;
28add0
+    int xoff, yoff;
28add0
+
28add0
+    if ((pPixmap = get_window_pixmap (pDrawable, &xoff, &yoff)))
28add0
+    {
28add0
+	int nbox = REGION_NUM_RECTS (pRegion);
28add0
+	BoxPtr pBox = REGION_RECTS (pRegion);
28add0
+
28add0
+	while (nbox--)
28add0
+	{
28add0
+	    struct qxl_rect qrect;
28add0
+
28add0
+	    qrect.left = pBox->x1;
28add0
+	    qrect.right = pBox->x2;
28add0
+	    qrect.top = pBox->y1;
28add0
+	    qrect.bottom = pBox->y2;
28add0
+
28add0
+	    submit_fill (qxl, &qrect, pixel);
28add0
+
28add0
+	    pBox++;
28add0
+	}
28add0
+    }
28add0
+
28add0
+    fbFillRegionSolid (pDrawable, pRegion, 0,
28add0
+		       fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_copy_window (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
28add0
+{
28add0
+    RegionRec rgnDst;
28add0
+    int dx, dy;
28add0
+
28add0
+    dx = ptOldOrg.x - pWin->drawable.x;
28add0
+    dy = ptOldOrg.y - pWin->drawable.y;
28add0
+
28add0
+    REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
28add0
+
28add0
+    REGION_INIT (pScreen, &rgnDst, NullBox, 0);
28add0
+
28add0
+    REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
28add0
+
28add0
+    fbCopyRegion (&pWin->drawable, &pWin->drawable,
28add0
+		  NULL, 
28add0
+		  &rgnDst, dx, dy, qxl_copy_n_to_n, 0, NULL);
28add0
+
28add0
+    REGION_UNINIT (pScreen, &rgnDst);
28add0
+
28add0
+/*     REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); */
28add0
+    
28add0
+/*     fbCopyWindow (pWin, ptOldOrg, prgnSrc); */
28add0
+}
28add0
+
28add0
+static int
28add0
+qxl_create_gc (GCPtr pGC)
28add0
+{
28add0
+    static GCOps ops;
28add0
+    static int initialized;
28add0
+    
28add0
+    if (!fbCreateGC (pGC))
28add0
+	return FALSE;
28add0
+
28add0
+    if (!initialized)
28add0
+    {
28add0
+	ops = *pGC->ops;
28add0
+	ops.PolyFillRect = qxl_poly_fill_rect;
28add0
+	ops.CopyArea = qxl_copy_area;
28add0
+
28add0
+	initialized = TRUE;
28add0
+    }
28add0
+    
28add0
+    pGC->ops = &ops;
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    struct qxl_rom *rom;
28add0
+    struct qxl_ram_header *ram_header;
28add0
+    VisualPtr visual;
28add0
+
28add0
+    CHECK_POINT();
28add0
+
28add0
+    qxl->pScrn = pScrn;
28add0
+    
28add0
+    if (!qxl_map_memory(qxl, scrnIndex))
28add0
+	return FALSE;
28add0
+
28add0
+    rom = qxl->rom;
28add0
+    ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
28add0
+
28add0
+    qxl_save_state(pScrn);
28add0
+    qxl_blank_screen(pScreen, SCREEN_SAVER_ON);
28add0
+    
28add0
+    miClearVisualTypes();
28add0
+    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
28add0
+			  pScrn->rgbBits, pScrn->defaultVisual))
28add0
+	goto out;
28add0
+    if (!miSetPixmapDepths())
28add0
+	goto out;
28add0
+
28add0
+    /* Note we do this before setting pScrn->virtualY to match our current
28add0
+       mode, so as to allocate a buffer large enough for the largest mode.
28add0
+       FIXME: add support for resizing the framebuffer on modeset. */
28add0
+    qxl->fb = xcalloc(pScrn->virtualY * pScrn->displayWidth, 4);
28add0
+    if (!qxl->fb)
28add0
+	goto out;
28add0
+
28add0
+    pScrn->virtualX = pScrn->currentMode->HDisplay;
28add0
+    pScrn->virtualY = pScrn->currentMode->VDisplay;
28add0
+    
28add0
+    if (!fbScreenInit(pScreen, qxl->fb,
28add0
+		      pScrn->currentMode->HDisplay,
28add0
+		      pScrn->currentMode->VDisplay,
28add0
+		      pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
28add0
+		      pScrn->bitsPerPixel))
28add0
+    {
28add0
+	goto out;
28add0
+    }
28add0
+
28add0
+    visual = pScreen->visuals + pScreen->numVisuals;
28add0
+    while (--visual >= pScreen->visuals) 
28add0
+    {
28add0
+	if ((visual->class | DynamicClass) == DirectColor) 
28add0
+	{
28add0
+	    visual->offsetRed = pScrn->offset.red;
28add0
+	    visual->offsetGreen = pScrn->offset.green;
28add0
+	    visual->offsetBlue = pScrn->offset.blue;
28add0
+	    visual->redMask = pScrn->mask.red;
28add0
+	    visual->greenMask = pScrn->mask.green;
28add0
+	    visual->blueMask = pScrn->mask.blue;
28add0
+	}
28add0
+    }
28add0
+
28add0
+    
28add0
+    fbPictureInit(pScreen, 0, 0);
28add0
+
28add0
+    qxl->create_screen_resources = pScreen->CreateScreenResources;
28add0
+    pScreen->CreateScreenResources = qxl_create_screen_resources;
28add0
+
28add0
+    /* Set up resources */
28add0
+    qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->ram + (unsigned long)rom->pages_offset),
28add0
+			       rom->num_io_pages * getpagesize());
28add0
+    qxl->io_pages = (void *)((unsigned long)qxl->ram + (unsigned long)rom->pages_offset);
28add0
+    qxl->io_pages_physical = (void *)((unsigned long)qxl->ram_physical + (unsigned long)rom->pages_offset);
28add0
+
28add0
+    qxl->command_ring = qxl_ring_create (&(ram_header->cmd_ring_hdr),
28add0
+					 sizeof (struct qxl_command),
28add0
+					 32, qxl->io_base + QXL_IO_NOTIFY_CMD);
28add0
+    qxl->cursor_ring = qxl_ring_create (&(ram_header->cursor_ring_hdr),
28add0
+					sizeof (struct qxl_command),
28add0
+					32, qxl->io_base + QXL_IO_NOTIFY_CURSOR);
28add0
+    qxl->release_ring = qxl_ring_create (&(ram_header->release_ring_hdr),
28add0
+					 sizeof (uint64_t),
28add0
+					 8, 0);
28add0
+					 
28add0
+    /* xf86DPMSInit(pScreen, xf86DPMSSet, 0); */
28add0
+
28add0
+#if 0 /* XV accel */
28add0
+    qxlInitVideo(pScreen);
28add0
+#endif
28add0
+
28add0
+    pScreen->SaveScreen = qxl_blank_screen;
28add0
+    qxl->close_screen = pScreen->CloseScreen;
28add0
+    pScreen->CloseScreen = qxl_close_screen;
28add0
+
28add0
+    qxl->create_gc = pScreen->CreateGC;
28add0
+    pScreen->CreateGC = qxl_create_gc;
28add0
+
28add0
+#if 0
28add0
+    qxl->paint_window_background = pScreen->PaintWindowBackground;
28add0
+    qxl->paint_window_border = pScreen->PaintWindowBorder;
28add0
+#endif
28add0
+    qxl->copy_window = pScreen->CopyWindow;
28add0
+#if 0
28add0
+    pScreen->PaintWindowBackground = qxl_paint_window;
28add0
+    pScreen->PaintWindowBorder = qxl_paint_window;
28add0
+#endif
28add0
+    pScreen->CopyWindow = qxl_copy_window;
28add0
+
28add0
+    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
28add0
+
28add0
+    if (!miCreateDefColormap(pScreen))
28add0
+	goto out;
28add0
+
28add0
+    qxl_cursor_init (pScreen);
28add0
+    
28add0
+    CHECK_POINT();
28add0
+
28add0
+    qxl_switch_mode(scrnIndex, pScrn->currentMode, 0);
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    return TRUE;
28add0
+
28add0
+out:
28add0
+    return FALSE;
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_enter_vt(int scrnIndex, int flags)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
28add0
+
28add0
+    qxl_save_state(pScrn);
28add0
+    qxl_switch_mode(scrnIndex, pScrn->currentMode, 0);
28add0
+
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_leave_vt(int scrnIndex, int flags)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
28add0
+
28add0
+    qxl_restore_state(pScrn);
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_color_setup(ScrnInfoPtr pScrn)
28add0
+{
28add0
+    int scrnIndex = pScrn->scrnIndex;
28add0
+    Gamma gzeros = { 0.0, 0.0, 0.0 };
28add0
+    rgb rzeros = { 0, 0, 0 };
28add0
+
28add0
+    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
28add0
+	return FALSE;
28add0
+
28add0
+    if (pScrn->depth != 15 && pScrn->depth != 24) 
28add0
+    {
28add0
+	xf86DrvMsg(scrnIndex, X_ERROR, "Depth %d is not supported\n",
28add0
+		   pScrn->depth);
28add0
+	return FALSE;
28add0
+    }
28add0
+    xf86PrintDepthBpp(pScrn);
28add0
+
28add0
+    if (!xf86SetWeight(pScrn, rzeros, rzeros))
28add0
+	return FALSE;
28add0
+
28add0
+    if (!xf86SetDefaultVisual(pScrn, -1))
28add0
+	return FALSE;
28add0
+
28add0
+    if (!xf86SetGamma(pScrn, gzeros))
28add0
+	return FALSE;
28add0
+
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static void
28add0
+print_modes (qxl_screen_t *qxl, int scrnIndex)
28add0
+{
28add0
+    int i;
28add0
+
28add0
+    for (i = 0; i < qxl->num_modes; ++i)
28add0
+    {
28add0
+	struct qxl_mode *m = qxl->modes + i;
28add0
+
28add0
+	xf86DrvMsg (scrnIndex, X_INFO,
28add0
+		    "%d: %dx%d, %d bits, stride %d, %dmm x %dmm, orientation %d\n",
28add0
+		    m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili,
28add0
+		    m->y_mili, m->orientation);
28add0
+    }
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_check_device(ScrnInfoPtr pScrn, qxl_screen_t *qxl)
28add0
+{
28add0
+    int scrnIndex = pScrn->scrnIndex;
28add0
+    struct qxl_rom *rom = qxl->rom;
28add0
+    struct qxl_ram_header *ram_header = (void *)((unsigned long)qxl->ram + rom->ram_header_offset);
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    if (rom->magic != 0x4f525851) { /* "QXRO" little-endian */
28add0
+	xf86DrvMsg(scrnIndex, X_ERROR, "Bad ROM signature %x\n", rom->magic);
28add0
+	return FALSE;
28add0
+    }
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "Device version %d.%d\n",
28add0
+	       rom->id, rom->update_id);
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "Compression level %d, log level %d\n",
28add0
+	       rom->compression_level,
28add0
+	       rom->log_level);
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "Currently using mode #%d, list at 0x%x\n",
28add0
+	       rom->mode, rom->modes_offset);
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "%d io pages at 0x%x\n",
28add0
+	       rom->num_io_pages, rom->pages_offset);
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "%d byte draw area at 0x%x\n",
28add0
+	       rom->draw_area_size, rom->draw_area_offset);
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "RAM header offset: 0x%x\n", rom->ram_header_offset);
28add0
+
28add0
+    if (ram_header->magic != 0x41525851) { /* "QXRA" little-endian */
28add0
+	xf86DrvMsg(scrnIndex, X_ERROR, "Bad RAM signature %x at %p\n",
28add0
+		   ram_header->magic,
28add0
+		   &ram_header->magic);
28add0
+	return FALSE;
28add0
+    }
28add0
+
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "Correct RAM signature %x\n", 
28add0
+	       ram_header->magic);
28add0
+
28add0
+    qxl->draw_area_offset = rom->draw_area_offset;
28add0
+    qxl->draw_area_size = rom->draw_area_size;
28add0
+    pScrn->videoRam = rom->draw_area_size / 1024;
28add0
+    
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+static int
28add0
+qxl_find_native_mode(ScrnInfoPtr pScrn, DisplayModePtr p)
28add0
+{
28add0
+    int i;
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    for (i = 0; i < qxl->num_modes; i++) 
28add0
+    {
28add0
+	struct qxl_mode *m = qxl->modes + i;
28add0
+
28add0
+	if (m->x_res == p->HDisplay &&
28add0
+	    m->y_res == p->VDisplay &&
28add0
+	    m->bits == pScrn->bitsPerPixel)
28add0
+	{
28add0
+	    if (m->bits == 16) 
28add0
+	    {
28add0
+		/* What QXL calls 16 bit is actually x1r5g5b515 */
28add0
+		if (pScrn->depth == 15)
28add0
+		    return i;
28add0
+	    }
28add0
+	    else if (m->bits == 32)
28add0
+	    {
28add0
+		/* What QXL calls 32 bit is actually x8r8g8b8 */
28add0
+		if (pScrn->depth == 24)
28add0
+		    return i;
28add0
+	    }
28add0
+	}
28add0
+    }
28add0
+
28add0
+    return -1;
28add0
+}
28add0
+
28add0
+static ModeStatus
28add0
+qxl_valid_mode(int scrn, DisplayModePtr p, Bool flag, int pass)
28add0
+{
28add0
+    ScrnInfoPtr pScrn = xf86Screens[scrn];
28add0
+    qxl_screen_t *qxl = pScrn->driverPrivate;
28add0
+    int bpp = pScrn->bitsPerPixel;
28add0
+    int mode_idx;
28add0
+
28add0
+    /* FIXME: I don't think this is necessary now that we report the
28add0
+     * correct amount of video ram?
28add0
+     */
28add0
+    if (p->HDisplay * p->VDisplay * (bpp/8) > qxl->draw_area_size)
28add0
+	return MODE_MEM;
28add0
+
28add0
+    mode_idx = qxl_find_native_mode (pScrn, p);
28add0
+    if (mode_idx == -1)
28add0
+	return MODE_NOMODE;
28add0
+
28add0
+    p->Private = (void *)(unsigned long)mode_idx;
28add0
+    
28add0
+    return MODE_OK;
28add0
+}
28add0
+
28add0
+static void qxl_add_mode(ScrnInfoPtr pScrn, int width, int height, int type)
28add0
+{
28add0
+    DisplayModePtr mode;
28add0
+
28add0
+    /* Skip already present modes */
28add0
+    for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
28add0
+        if (mode->HDisplay == width && mode->VDisplay == height)
28add0
+            return;
28add0
+
28add0
+    mode = xnfcalloc(1, sizeof(DisplayModeRec));
28add0
+
28add0
+    mode->status = MODE_OK;
28add0
+    mode->type = type;
28add0
+    mode->HDisplay   = width;
28add0
+    mode->HSyncStart = (width * 105 / 100 + 7) & ~7;
28add0
+    mode->HSyncEnd   = (width * 115 / 100 + 7) & ~7;
28add0
+    mode->HTotal     = (width * 130 / 100 + 7) & ~7;
28add0
+    mode->VDisplay   = height;
28add0
+    mode->VSyncStart = height + 1;
28add0
+    mode->VSyncEnd   = height + 4;
28add0
+    mode->VTotal     = height * 1035 / 1000;
28add0
+    mode->Clock = mode->HTotal * mode->VTotal * 60 / 1000;
28add0
+    mode->Flags = V_NHSYNC | V_PVSYNC;
28add0
+
28add0
+    xf86SetModeDefaultName(mode);
28add0
+    xf86ModesAdd(pScrn->monitor->Modes, mode);
28add0
+}
28add0
+
28add0
+static Bool
28add0
+qxl_pre_init(ScrnInfoPtr pScrn, int flags)
28add0
+{
28add0
+    int i, scrnIndex = pScrn->scrnIndex;
28add0
+    qxl_screen_t *qxl = NULL;
28add0
+    ClockRangePtr clockRanges = NULL;
28add0
+    int *linePitches = NULL;
28add0
+    DisplayModePtr mode;
28add0
+    unsigned int max_x = 0, max_y = 0;
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    /* zaphod mode is for suckers and i choose not to implement it */
28add0
+    if (xf86IsEntityShared(pScrn->entityList[0])) {
28add0
+	xf86DrvMsg(scrnIndex, X_ERROR, "No Zaphod mode for you\n");
28add0
+	return FALSE;
28add0
+    }
28add0
+
28add0
+    if (!pScrn->driverPrivate)
28add0
+	pScrn->driverPrivate = xnfcalloc(sizeof(qxl_screen_t), 1);
28add0
+    qxl = pScrn->driverPrivate;
28add0
+    
28add0
+    qxl->entity = xf86GetEntityInfo(pScrn->entityList[0]);
28add0
+    qxl->pci = xf86GetPciInfoForEntity(qxl->entity->index);
28add0
+#ifndef XSERVER_LIBPCIACCESS
28add0
+    qxl->pci_tag = pciTag(qxl->pci->bus, qxl->pci->device, qxl->pci->func);
28add0
+#endif
28add0
+
28add0
+    pScrn->monitor = pScrn->confScreen->monitor;
28add0
+
28add0
+    if (!qxl_color_setup(pScrn))
28add0
+	goto out;
28add0
+
28add0
+    /* option parsing and card differentiation */
28add0
+    xf86CollectOptions(pScrn, NULL);
28add0
+    
28add0
+    if (!qxl_map_memory(qxl, scrnIndex))
28add0
+	goto out;
28add0
+
28add0
+    if (!qxl_check_device(pScrn, qxl))
28add0
+	goto out;
28add0
+
28add0
+    /* ddc stuff here */
28add0
+
28add0
+    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
28add0
+    clockRanges->next = NULL;
28add0
+    clockRanges->minClock = 10000;
28add0
+    clockRanges->maxClock = 400000;
28add0
+    clockRanges->clockIndex = -1;
28add0
+    clockRanges->interlaceAllowed = clockRanges->doubleScanAllowed = 0;
28add0
+    clockRanges->ClockMulFactor = clockRanges->ClockDivFactor = 1;
28add0
+    pScrn->progClock = TRUE;
28add0
+
28add0
+    /* override QXL monitor stuff */
28add0
+    if (pScrn->monitor->nHsync <= 0) {
28add0
+	pScrn->monitor->hsync[0].lo =  29.0;
28add0
+	pScrn->monitor->hsync[0].hi = 160.0;
28add0
+	pScrn->monitor->nHsync = 1;
28add0
+    }
28add0
+    if (pScrn->monitor->nVrefresh <= 0) {
28add0
+	pScrn->monitor->vrefresh[0].lo = 50;
28add0
+	pScrn->monitor->vrefresh[0].hi = 75;
28add0
+	pScrn->monitor->nVrefresh = 1;
28add0
+    }
28add0
+
28add0
+    /* Add any modes not in xorg's default mode list */
28add0
+    for (i = 0; i < qxl->num_modes; i++)
28add0
+        if (qxl->modes[i].orientation == 0) {
28add0
+            qxl_add_mode(pScrn, qxl->modes[i].x_res, qxl->modes[i].y_res,
28add0
+                         M_T_DRIVER);
28add0
+            if (qxl->modes[i].x_res > max_x)
28add0
+                max_x = qxl->modes[i].x_res;
28add0
+            if (qxl->modes[i].y_res > max_y)
28add0
+                max_y = qxl->modes[i].y_res;
28add0
+        }
28add0
+
28add0
+    if (pScrn->display->virtualX == 0 && pScrn->display->virtualY == 0) {
28add0
+        /* It is possible for the largest x + largest y size combined leading
28add0
+           to a virtual size which will not fit into the framebuffer when this
28add0
+           happens we prefer max width and make height as large as possible */
28add0
+        if (max_x * max_y * (pScrn->bitsPerPixel / 8) > qxl->draw_area_size)
28add0
+            pScrn->display->virtualY = qxl->draw_area_size /
28add0
+                                       (max_x * (pScrn->bitsPerPixel / 8));
28add0
+        else
28add0
+            pScrn->display->virtualY = max_y;
28add0
+
28add0
+    	pScrn->display->virtualX = max_x;
28add0
+    }
28add0
+
28add0
+    if (0 >= xf86ValidateModes(pScrn, pScrn->monitor->Modes,
28add0
+			       pScrn->display->modes, clockRanges, linePitches,
28add0
+			       128, max_x, 128 * 4, 128, max_y,
28add0
+			       pScrn->display->virtualX,
28add0
+			       pScrn->display->virtualY,
28add0
+			       128 * 1024 * 1024, LOOKUP_BEST_REFRESH))
28add0
+	goto out;
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    xf86PruneDriverModes(pScrn);
28add0
+    pScrn->currentMode = pScrn->modes;
28add0
+    /* If no modes are specified in xorg.conf, default to 1024x768 */
28add0
+    if (pScrn->display->modes == NULL || pScrn->display->modes[0] == NULL)
28add0
+        for (mode = pScrn->modes; mode; mode = mode->next)
28add0
+            if (mode->HDisplay == 1024 && mode->VDisplay == 768) {
28add0
+                pScrn->currentMode = mode;
28add0
+                break;
28add0
+            }
28add0
+
28add0
+    xf86PrintModes(pScrn);
28add0
+    xf86SetDpi(pScrn, 0, 0);
28add0
+
28add0
+    if (!xf86LoadSubModule(pScrn, "fb") ||
28add0
+	!xf86LoadSubModule(pScrn, "ramdac") ||
28add0
+	!xf86LoadSubModule(pScrn, "vgahw"))
28add0
+    {
28add0
+	goto out;
28add0
+    }
28add0
+
28add0
+    print_modes (qxl, scrnIndex);
28add0
+
28add0
+    /* VGA hardware initialisation */
28add0
+    if (!vgaHWGetHWRec(pScrn))
28add0
+        return FALSE;
28add0
+
28add0
+    /* hate */
28add0
+    qxl_unmap_memory(qxl, scrnIndex);
28add0
+
28add0
+    CHECK_POINT();
28add0
+    
28add0
+    xf86DrvMsg(scrnIndex, X_INFO, "PreInit complete\n");
28add0
+    return TRUE;
28add0
+
28add0
+out:
28add0
+    if (clockRanges)
28add0
+	xfree(clockRanges);
28add0
+    if (qxl)
28add0
+	xfree(qxl);
28add0
+
28add0
+    return FALSE;
28add0
+}
28add0
+
28add0
+#ifdef XSERVER_LIBPCIACCESS
28add0
+enum qxl_class
28add0
+{
28add0
+    CHIP_QXL_1,
28add0
+};
28add0
+
28add0
+static const struct pci_id_match qxl_device_match[] = {
28add0
+    {
28add0
+	PCI_VENDOR_RED_HAT, PCI_CHIP_QXL_0100, PCI_MATCH_ANY, PCI_MATCH_ANY,
28add0
+	0x00030000, 0x00ffffff, CHIP_QXL_1
28add0
+    },
28add0
+
28add0
+    { 0 },
28add0
+};
28add0
+#endif
28add0
+
28add0
+static SymTabRec qxlChips[] =
28add0
+{
28add0
+    { PCI_CHIP_QXL_0100,	"QXL 1", },
28add0
+    { -1, NULL }
28add0
+};
28add0
+
28add0
+#ifndef XSERVER_LIBPCIACCESS
28add0
+static PciChipsets qxlPciChips[] =
28add0
+{
28add0
+    { PCI_CHIP_QXL_0100,    PCI_CHIP_QXL_0100,	RES_SHARED_VGA },
28add0
+    { -1, -1, RES_UNDEFINED }
28add0
+};
28add0
+#endif
28add0
+
28add0
+static void
28add0
+qxl_identify(int flags)
28add0
+{
28add0
+    xf86PrintChipsets("qxl", "Driver for QXL virtual graphics", qxlChips);
28add0
+}
28add0
+
28add0
+static void
28add0
+qxl_init_scrn(ScrnInfoPtr pScrn)
28add0
+{
28add0
+    pScrn->driverVersion    = 0;
28add0
+    pScrn->driverName	    = pScrn->name = "qxl";
28add0
+    pScrn->PreInit	    = qxl_pre_init;
28add0
+    pScrn->ScreenInit	    = qxl_screen_init;
28add0
+    pScrn->SwitchMode	    = qxl_switch_mode;
28add0
+    pScrn->ValidMode	    = qxl_valid_mode;
28add0
+    pScrn->EnterVT	    = qxl_enter_vt;
28add0
+    pScrn->LeaveVT	    = qxl_leave_vt;
28add0
+}
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-qxl.h.compat xf86-video-qxl-20130514/src/compat/compat-qxl.h
28add0
--- xf86-video-qxl-20130514/src/compat/compat-qxl.h.compat	2013-07-03 14:18:57.094319233 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-qxl.h	2013-07-03 14:18:57.094319233 +1000
28add0
@@ -0,0 +1,610 @@
28add0
+/*
28add0
+ * Copyright 2008 Red Hat, Inc.
28add0
+ *
28add0
+ * Permission is hereby granted, free of charge, to any person obtaining a
28add0
+ * copy of this software and associated documentation files (the "Software"),
28add0
+ * to deal in the Software without restriction, including without limitation
28add0
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
28add0
+ * license, and/or sell copies of the Software, and to permit persons to whom
28add0
+ * the Software is furnished to do so, subject to the following conditions:
28add0
+ *
28add0
+ * The above copyright notice and this permission notice (including the next
28add0
+ * paragraph) shall be included in all copies or substantial portions of the
28add0
+ * Software.
28add0
+ *
28add0
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28add0
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28add0
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
28add0
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
28add0
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28add0
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28add0
+ */
28add0
+
28add0
+#include "config.h"
28add0
+
28add0
+#include <stdint.h>
28add0
+
28add0
+#include "compiler.h"
28add0
+#include "xf86.h"
28add0
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
28add0
+#include "xf86Resources.h"
28add0
+#endif
28add0
+#include "xf86PciInfo.h"
28add0
+#include "xf86Cursor.h"
28add0
+#include "xf86_OSproc.h"
28add0
+#include "xf86xv.h"
28add0
+#include "shadow.h"
28add0
+#include "micmap.h"
28add0
+#ifdef XSERVER_PCIACCESS
28add0
+#include "pciaccess.h"
28add0
+#endif
28add0
+#include "fb.h"
28add0
+#include "vgaHW.h"
28add0
+
28add0
+#define hidden _X_HIDDEN
28add0
+
28add0
+#define QXL_NAME		"qxl"
28add0
+#define QXL_DRIVER_NAME		"qxl"
28add0
+#define PCI_VENDOR_RED_HAT	0x1b36
28add0
+
28add0
+#define PCI_CHIP_QXL_0100	0x0100
28add0
+
28add0
+#pragma pack(push,1)
28add0
+
28add0
+/* I/O port definitions */
28add0
+enum {
28add0
+    QXL_IO_NOTIFY_CMD,
28add0
+    QXL_IO_NOTIFY_CURSOR,
28add0
+    QXL_IO_UPDATE_AREA,
28add0
+    QXL_IO_UPDATE_IRQ,
28add0
+    QXL_IO_NOTIFY_OOM,
28add0
+    QXL_IO_RESET,
28add0
+    QXL_IO_SET_MODE,
28add0
+    QXL_IO_LOG,
28add0
+};
28add0
+
28add0
+struct qxl_mode {
28add0
+    uint32_t id;
28add0
+    uint32_t x_res;
28add0
+    uint32_t y_res;
28add0
+    uint32_t bits;
28add0
+    uint32_t stride;
28add0
+    uint32_t x_mili;
28add0
+    uint32_t y_mili;
28add0
+    uint32_t orientation;
28add0
+};
28add0
+
28add0
+typedef enum
28add0
+{
28add0
+    QXL_CMD_NOP,
28add0
+    QXL_CMD_DRAW,
28add0
+    QXL_CMD_UPDATE,
28add0
+    QXL_CMD_CURSOR,
28add0
+    QXL_CMD_MESSAGE
28add0
+} qxl_command_type;
28add0
+
28add0
+struct qxl_command {
28add0
+    uint64_t data;
28add0
+    uint32_t type;
28add0
+    uint32_t pad;
28add0
+};
28add0
+
28add0
+struct qxl_rect {
28add0
+    uint32_t top;
28add0
+    uint32_t left;
28add0
+    uint32_t bottom;
28add0
+    uint32_t right;
28add0
+};
28add0
+
28add0
+union qxl_release_info {
28add0
+    uint64_t id;
28add0
+    uint64_t next;
28add0
+};
28add0
+
28add0
+struct qxl_clip {
28add0
+    uint32_t type;
28add0
+    uint64_t address;
28add0
+};
28add0
+
28add0
+struct qxl_point {
28add0
+    int x;
28add0
+    int y;
28add0
+};
28add0
+
28add0
+struct qxl_pattern {
28add0
+    uint64_t pat;
28add0
+    struct qxl_point pos;
28add0
+};
28add0
+
28add0
+typedef enum
28add0
+{
28add0
+    QXL_BRUSH_TYPE_NONE,
28add0
+    QXL_BRUSH_TYPE_SOLID,
28add0
+    QXL_BRUSH_TYPE_PATTERN
28add0
+} qxl_brush_type;
28add0
+
28add0
+struct qxl_brush {
28add0
+    uint32_t type;
28add0
+    union {
28add0
+	uint32_t color;
28add0
+	struct qxl_pattern pattern;
28add0
+    } u;
28add0
+};
28add0
+
28add0
+struct qxl_mask {
28add0
+    unsigned char flags;
28add0
+    struct qxl_point pos;
28add0
+    uint64_t bitmap;
28add0
+};
28add0
+
28add0
+typedef enum {
28add0
+    QXL_IMAGE_TYPE_BITMAP,
28add0
+    QXL_IMAGE_TYPE_QUIC,
28add0
+    QXL_IMAGE_TYPE_PNG,
28add0
+    QXL_IMAGE_TYPE_LZ_PLT = 100,
28add0
+    QXL_IMAGE_TYPE_LZ_RGB,
28add0
+    QXL_IMAGE_TYPE_GLZ_RGB,
28add0
+    QXL_IMAGE_TYPE_FROM_CACHE,
28add0
+} qxl_image_type;
28add0
+
28add0
+typedef enum {
28add0
+    QXL_IMAGE_CACHE = (1 << 0)
28add0
+} qxl_image_flags;
28add0
+
28add0
+struct qxl_image_descriptor
28add0
+{
28add0
+    uint64_t id;
28add0
+    uint8_t type;
28add0
+    uint8_t flags;
28add0
+    uint32_t width;
28add0
+    uint32_t height;
28add0
+};
28add0
+
28add0
+struct qxl_data_chunk {
28add0
+    uint32_t data_size;
28add0
+    uint64_t prev_chunk;
28add0
+    uint64_t next_chunk;
28add0
+    uint8_t data[0];
28add0
+};
28add0
+
28add0
+typedef enum
28add0
+{
28add0
+    QXL_BITMAP_FMT_INVALID,
28add0
+    QXL_BITMAP_FMT_1BIT_LE,
28add0
+    QXL_BITMAP_FMT_1BIT_BE,
28add0
+    QXL_BITMAP_FMT_4BIT_LE,
28add0
+    QXL_BITMAP_FMT_4BIT_BE,
28add0
+    QXL_BITMAP_FMT_8BIT,
28add0
+    QXL_BITMAP_FMT_16BIT,
28add0
+    QXL_BITMAP_FMT_24BIT,
28add0
+    QXL_BITMAP_FMT_32BIT,
28add0
+    QXL_BITMAP_FMT_RGBA,
28add0
+} qxl_bitmap_format;
28add0
+
28add0
+typedef enum {
28add0
+    QXL_BITMAP_PAL_CACHE_ME = (1 << 0),
28add0
+    QXL_BITMAP_PAL_FROM_CACHE = (1 << 1),
28add0
+    QXL_BITMAP_TOP_DOWN = (1 << 2),
28add0
+} qxl_bitmap_flags;
28add0
+
28add0
+struct qxl_bitmap {
28add0
+    uint8_t format;
28add0
+    uint8_t flags;		
28add0
+    uint32_t x;			/* actually width */
28add0
+    uint32_t y;			/* actually height */
28add0
+    uint32_t stride;		/* in bytes */
28add0
+    uint64_t palette;		/* Can be NULL */
28add0
+    uint64_t data;		/* A qxl_data_chunk that actually contains the data */
28add0
+};
28add0
+
28add0
+struct qxl_image {
28add0
+    struct qxl_image_descriptor descriptor;
28add0
+    union
28add0
+    {
28add0
+	struct qxl_bitmap bitmap;
28add0
+    } u;
28add0
+};
28add0
+
28add0
+struct qxl_fill {
28add0
+    struct qxl_brush brush;
28add0
+    unsigned short rop_descriptor;
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_opaque {
28add0
+    uint64_t src_bitmap;
28add0
+    struct qxl_rect src_area;
28add0
+    struct qxl_brush brush;
28add0
+    unsigned short rop_descriptor;
28add0
+    unsigned char scale_mode;
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_copy {
28add0
+    uint64_t src_bitmap;
28add0
+    struct qxl_rect src_area;
28add0
+    unsigned short rop_descriptor;
28add0
+    unsigned char scale_mode;
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_transparent {
28add0
+    uint64_t src_bitmap;
28add0
+    struct qxl_rect src_area;
28add0
+    uint32_t src_color;
28add0
+    uint32_t true_color;
28add0
+};
28add0
+
28add0
+struct qxl_alpha_blend {
28add0
+    unsigned char alpha;
28add0
+    uint64_t src_bitmap;
28add0
+    struct qxl_rect src_area;
28add0
+};
28add0
+
28add0
+struct qxl_copy_bits {
28add0
+    struct qxl_point src_pos;
28add0
+};
28add0
+
28add0
+struct qxl_blend { /* same as copy */
28add0
+    uint64_t src_bitmap;
28add0
+    struct qxl_rect src_area;
28add0
+    unsigned short rop_descriptor;
28add0
+    unsigned char scale_mode;
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_rop3 {
28add0
+    uint64_t src_bitmap;
28add0
+    struct qxl_rect src_area;
28add0
+    struct qxl_brush brush;
28add0
+    unsigned char rop3;
28add0
+    unsigned char scale_mode;
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_line_attr {
28add0
+    unsigned char flags;
28add0
+    unsigned char join_style;
28add0
+    unsigned char end_style;
28add0
+    unsigned char style_nseg;
28add0
+    int width;
28add0
+    int miter_limit;
28add0
+    uint64_t style;
28add0
+};
28add0
+
28add0
+struct qxl_stroke {
28add0
+    uint64_t path;
28add0
+    struct qxl_line_attr attr;
28add0
+    struct qxl_brush brush;
28add0
+    unsigned short fore_mode;
28add0
+    unsigned short back_mode;
28add0
+};
28add0
+
28add0
+struct qxl_text {
28add0
+    uint64_t str;
28add0
+    struct qxl_rect back_area;
28add0
+    struct qxl_brush fore_brush;
28add0
+    struct qxl_brush back_brush;
28add0
+    unsigned short fore_mode;
28add0
+    unsigned short back_mode;
28add0
+};
28add0
+
28add0
+struct qxl_blackness {
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_inverse {
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+struct qxl_whiteness {
28add0
+    struct qxl_mask mask;
28add0
+};
28add0
+
28add0
+/* Effects */
28add0
+typedef enum
28add0
+{
28add0
+    QXL_EFFECT_BLEND,
28add0
+    QXL_EFFECT_OPAQUE,
28add0
+    QXL_EFFECT_REVERT_ON_DUP,
28add0
+    QXL_EFFECT_BLACKNESS_ON_DUP,
28add0
+    QXL_EFFECT_WHITENESS_ON_DUP,
28add0
+    QXL_EFFECT_NOP_ON_DUP,
28add0
+    QXL_EFFECT_NOP,
28add0
+    QXL_EFFECT_OPAQUE_BRUSH
28add0
+} qxl_effect_type;
28add0
+
28add0
+typedef enum
28add0
+{
28add0
+    QXL_CLIP_TYPE_NONE,
28add0
+    QXL_CLIP_TYPE_RECTS,
28add0
+    QXL_CLIP_TYPE_PATH,
28add0
+} qxl_clip_type;
28add0
+
28add0
+typedef enum {
28add0
+    QXL_DRAW_NOP,
28add0
+    QXL_DRAW_FILL,
28add0
+    QXL_DRAW_OPAQUE,
28add0
+    QXL_DRAW_COPY,
28add0
+    QXL_COPY_BITS,
28add0
+    QXL_DRAW_BLEND,
28add0
+    QXL_DRAW_BLACKNESS,
28add0
+    QXL_DRAW_WHITENESS,
28add0
+    QXL_DRAW_INVERS,
28add0
+    QXL_DRAW_ROP3,
28add0
+    QXL_DRAW_STROKE,
28add0
+    QXL_DRAW_TEXT,
28add0
+    QXL_DRAW_TRANSPARENT,
28add0
+    QXL_DRAW_ALPHA_BLEND,
28add0
+} qxl_draw_type;
28add0
+
28add0
+struct qxl_drawable {
28add0
+    union qxl_release_info release_info;
28add0
+    unsigned char effect;
28add0
+    unsigned char type;
28add0
+    unsigned short bitmap_offset;
28add0
+    struct qxl_rect bitmap_area;
28add0
+    struct qxl_rect bbox;
28add0
+    struct qxl_clip clip;
28add0
+    uint32_t mm_time;
28add0
+    union {
28add0
+	struct qxl_fill fill;
28add0
+	struct qxl_opaque opaque;
28add0
+	struct qxl_copy copy;
28add0
+	struct qxl_transparent transparent;
28add0
+	struct qxl_alpha_blend alpha_blend;
28add0
+	struct qxl_copy_bits copy_bits;
28add0
+	struct qxl_blend blend;
28add0
+	struct qxl_rop3 rop3;
28add0
+	struct qxl_stroke stroke;
28add0
+	struct qxl_text text;
28add0
+	struct qxl_blackness blackness;
28add0
+	struct qxl_inverse inverse;
28add0
+	struct qxl_whiteness whiteness;
28add0
+    } u;
28add0
+};
28add0
+
28add0
+struct qxl_update_cmd {
28add0
+    union qxl_release_info release_info;
28add0
+    struct qxl_rect area;
28add0
+    uint32_t update_id;
28add0
+};
28add0
+
28add0
+struct qxl_point16 {
28add0
+    int16_t x;
28add0
+    int16_t y;
28add0
+};
28add0
+
28add0
+enum {
28add0
+    QXL_CURSOR_SET,
28add0
+    QXL_CURSOR_MOVE,
28add0
+    QXL_CURSOR_HIDE,
28add0
+    QXL_CURSOR_TRAIL,
28add0
+};
28add0
+
28add0
+#define QXL_CURSOR_DEVICE_DATA_SIZE 128
28add0
+
28add0
+enum {
28add0
+    CURSOR_TYPE_ALPHA,
28add0
+    CURSOR_TYPE_MONO,
28add0
+    CURSOR_TYPE_COLOR4,
28add0
+    CURSOR_TYPE_COLOR8,
28add0
+    CURSOR_TYPE_COLOR16,
28add0
+    CURSOR_TYPE_COLOR24,
28add0
+    CURSOR_TYPE_COLOR32,
28add0
+};
28add0
+
28add0
+struct qxl_cursor_header {
28add0
+    uint64_t unique;
28add0
+    uint16_t type;
28add0
+    uint16_t width;
28add0
+    uint16_t height;
28add0
+    uint16_t hot_spot_x;
28add0
+    uint16_t hot_spot_y;
28add0
+};
28add0
+
28add0
+struct qxl_cursor
28add0
+{
28add0
+    struct qxl_cursor_header header;
28add0
+    uint32_t data_size;
28add0
+    struct qxl_data_chunk chunk;
28add0
+};
28add0
+
28add0
+struct qxl_cursor_cmd {
28add0
+    union qxl_release_info release_info;
28add0
+    uint8_t type;
28add0
+    union {
28add0
+	struct {
28add0
+	    struct qxl_point16 position;
28add0
+	    unsigned char visible;
28add0
+	    uint64_t shape;
28add0
+	} set;
28add0
+	struct {
28add0
+	    uint16_t length;
28add0
+	    uint16_t frequency;
28add0
+	} trail;
28add0
+	struct qxl_point16 position;
28add0
+    } u;
28add0
+    uint8_t device_data[QXL_CURSOR_DEVICE_DATA_SIZE];
28add0
+};
28add0
+
28add0
+struct qxl_rom {
28add0
+    uint32_t magic;
28add0
+    uint32_t id;
28add0
+    uint32_t update_id;
28add0
+    uint32_t compression_level;
28add0
+    uint32_t log_level;
28add0
+    uint32_t mode;
28add0
+    uint32_t modes_offset;
28add0
+    uint32_t num_io_pages;
28add0
+    uint32_t pages_offset;
28add0
+    uint32_t draw_area_offset;
28add0
+    uint32_t draw_area_size;
28add0
+    uint32_t ram_header_offset;
28add0
+    uint32_t mm_clock;
28add0
+};
28add0
+
28add0
+struct qxl_ring_header {
28add0
+    uint32_t num_items;
28add0
+    uint32_t prod;
28add0
+    uint32_t notify_on_prod;
28add0
+    uint32_t cons;
28add0
+    uint32_t notify_on_cons;
28add0
+};
28add0
+
28add0
+#define QXL_LOG_BUF_SIZE 4096
28add0
+
28add0
+struct qxl_ram_header {
28add0
+    uint32_t magic;
28add0
+    uint32_t int_pending;
28add0
+    uint32_t int_mask;
28add0
+    unsigned char log_buf[QXL_LOG_BUF_SIZE];
28add0
+    struct qxl_ring_header  cmd_ring_hdr;
28add0
+    struct qxl_command	    cmd_ring[32];
28add0
+    struct qxl_ring_header  cursor_ring_hdr;
28add0
+    struct qxl_command	    cursor_ring[32];
28add0
+    struct qxl_ring_header  release_ring_hdr;
28add0
+    uint64_t		    release_ring[8];
28add0
+    struct qxl_rect	    update_area;
28add0
+};
28add0
+
28add0
+#pragma pack(pop)
28add0
+
28add0
+typedef struct _qxl_screen_t qxl_screen_t;
28add0
+
28add0
+struct _qxl_screen_t
28add0
+{
28add0
+    /* These are the names QXL uses */
28add0
+    void *			ram;	/* Video RAM */
28add0
+    void *			ram_physical;
28add0
+    void *			vram;	/* Command RAM */
28add0
+    struct qxl_rom *		rom;    /* Parameter RAM */
28add0
+    
28add0
+    struct qxl_ring *		command_ring;
28add0
+    struct qxl_ring *		cursor_ring;
28add0
+    struct qxl_ring *		release_ring;
28add0
+    
28add0
+    int				num_modes;
28add0
+    struct qxl_mode *		modes;
28add0
+    int				io_base;
28add0
+    int				draw_area_offset;
28add0
+    int				draw_area_size;
28add0
+
28add0
+    void *			fb;
28add0
+    int				bytes_per_pixel;
28add0
+
28add0
+    struct qxl_mem *		mem;	/* Context for qxl_alloc/free */
28add0
+    
28add0
+    EntityInfoPtr		entity;
28add0
+
28add0
+    void *			io_pages;
28add0
+    void *			io_pages_physical;
28add0
+    
28add0
+#ifdef XSERVER_LIBPCIACCESS
28add0
+    struct pci_device *		pci;
28add0
+#else
28add0
+    pciVideoPtr			pci;
28add0
+    PCITAG			pci_tag;
28add0
+#endif
28add0
+    vgaRegRec                   vgaRegs;
28add0
+
28add0
+    CreateScreenResourcesProcPtr create_screen_resources;
28add0
+    CloseScreenProcPtr		close_screen;
28add0
+    CreateGCProcPtr		create_gc;
28add0
+#if 0
28add0
+    PaintWindowProcPtr		paint_window_background;
28add0
+    PaintWindowProcPtr		paint_window_border;
28add0
+#endif
28add0
+    CopyWindowProcPtr		copy_window;
28add0
+    
28add0
+    DamagePtr			damage;
28add0
+    RegionRec			pending_copy;
28add0
+    RegionRec			to_be_sent;
28add0
+    
28add0
+    int16_t			cur_x;
28add0
+    int16_t			cur_y;
28add0
+    int16_t			hot_x;
28add0
+    int16_t			hot_y;
28add0
+    
28add0
+    ScrnInfoPtr			pScrn;
28add0
+};
28add0
+
28add0
+static inline uint64_t
28add0
+physical_address (qxl_screen_t *qxl, void *virtual)
28add0
+{
28add0
+    return (uint64_t) ((unsigned long)virtual + (((unsigned long)qxl->ram_physical - (unsigned long)qxl->ram)));
28add0
+}
28add0
+
28add0
+static inline void *
28add0
+virtual_address (qxl_screen_t *qxl, void *physical)
28add0
+{
28add0
+    return (void *) ((unsigned long)physical + ((unsigned long)qxl->ram - (unsigned long)qxl->ram_physical));
28add0
+}
28add0
+
28add0
+static inline void *
28add0
+u64_to_pointer (uint64_t u)
28add0
+{
28add0
+    return (void *)(unsigned long)u;
28add0
+}
28add0
+
28add0
+static inline uint64_t
28add0
+pointer_to_u64 (void *p)
28add0
+{
28add0
+    return (uint64_t)(unsigned long)p;
28add0
+}
28add0
+
28add0
+struct qxl_ring;
28add0
+
28add0
+/*
28add0
+ * HW cursor
28add0
+ */
28add0
+void              qxl_cursor_init        (ScreenPtr               pScreen);
28add0
+
28add0
+
28add0
+
28add0
+/*
28add0
+ * Rings
28add0
+ */
28add0
+struct qxl_ring * qxl_ring_create      (struct qxl_ring_header *header,
28add0
+					int                     element_size,
28add0
+					int                     n_elements,
28add0
+					int                     prod_notify);
28add0
+void              qxl_ring_push        (struct qxl_ring        *ring,
28add0
+					const void             *element);
28add0
+Bool              qxl_ring_pop         (struct qxl_ring        *ring,
28add0
+					void                   *element);
28add0
+void              qxl_ring_wait_idle   (struct qxl_ring        *ring);
28add0
+
28add0
+
28add0
+
28add0
+/*
28add0
+ * Images
28add0
+ */
28add0
+struct qxl_image *qxl_image_create     (qxl_screen_t           *qxl,
28add0
+					const uint8_t          *data,
28add0
+					int                     x,
28add0
+					int                     y,
28add0
+					int                     width,
28add0
+					int                     height,
28add0
+					int                     stride);
28add0
+void              qxl_image_destroy    (qxl_screen_t           *qxl,
28add0
+					struct qxl_image       *image);
28add0
+void		  qxl_drop_image_cache (qxl_screen_t	       *qxl);
28add0
+
28add0
+
28add0
+/*
28add0
+ * Malloc
28add0
+ */
28add0
+struct qxl_mem *  qxl_mem_create       (void                   *base,
28add0
+					unsigned long           n_bytes);
28add0
+void              qxl_mem_dump_stats   (struct qxl_mem         *mem,
28add0
+					const char             *header);
28add0
+void *            qxl_alloc            (struct qxl_mem         *mem,
28add0
+					unsigned long           n_bytes);
28add0
+void              qxl_free             (struct qxl_mem         *mem,
28add0
+					void                   *d);
28add0
+void              qxl_mem_free_all     (struct qxl_mem         *mem);
28add0
+void *            qxl_allocnf          (qxl_screen_t           *qxl,
28add0
+					unsigned long           size);
28add0
+
28add0
+
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-qxl_image.c.compat xf86-video-qxl-20130514/src/compat/compat-qxl_image.c
28add0
--- xf86-video-qxl-20130514/src/compat/compat-qxl_image.c.compat	2013-07-03 14:18:57.096319282 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-qxl_image.c	2013-07-03 14:18:57.096319282 +1000
28add0
@@ -0,0 +1,255 @@
28add0
+#include <string.h>
28add0
+#include <assert.h>
28add0
+#include <stdlib.h>
28add0
+#include "compat-qxl.h"
28add0
+#include "compat-lookup3.h"
28add0
+
28add0
+typedef struct image_info_t image_info_t;
28add0
+
28add0
+struct image_info_t
28add0
+{
28add0
+    struct qxl_image *image;
28add0
+    int ref_count;
28add0
+    image_info_t *next;
28add0
+};
28add0
+
28add0
+#define HASH_SIZE 4096
28add0
+static image_info_t *image_table[HASH_SIZE];
28add0
+
28add0
+static unsigned int
28add0
+hash_and_copy (const uint8_t *src, int src_stride,
28add0
+	       uint8_t *dest, int dest_stride,
28add0
+	       int bytes_per_pixel, int width, int height)
28add0
+{
28add0
+    unsigned int hash = 0;
28add0
+    int i;
28add0
+  
28add0
+    for (i = 0; i < height; ++i)
28add0
+    {
28add0
+	const uint8_t *src_line = src + i * src_stride;
28add0
+	uint8_t *dest_line = dest + i * dest_stride;
28add0
+	int n_bytes = width * bytes_per_pixel;
28add0
+
28add0
+	if (dest)
28add0
+	    memcpy (dest_line, src_line, n_bytes);
28add0
+
28add0
+	hash = hashlittle (src_line, n_bytes, hash);
28add0
+    }
28add0
+
28add0
+    return hash;
28add0
+}
28add0
+
28add0
+static image_info_t *
28add0
+lookup_image_info (unsigned int hash,
28add0
+		   int width,
28add0
+		   int height)
28add0
+{
28add0
+    struct image_info_t *info = image_table[hash % HASH_SIZE];
28add0
+
28add0
+    while (info)
28add0
+    {
28add0
+	struct qxl_image *image = info->image;
28add0
+
28add0
+	if (image->descriptor.id == hash		&&
28add0
+	    image->descriptor.width == width		&&
28add0
+	    image->descriptor.height == height)
28add0
+	{
28add0
+	    return info;
28add0
+	}
28add0
+
28add0
+	info = info->next;
28add0
+    }
28add0
+
28add0
+#if 0
28add0
+    ErrorF ("lookup of %u failed\n", hash);
28add0
+#endif
28add0
+    
28add0
+    return NULL;
28add0
+}
28add0
+
28add0
+static image_info_t *
28add0
+insert_image_info (unsigned int hash)
28add0
+{
28add0
+    struct image_info_t *info = malloc (sizeof (image_info_t));
28add0
+
28add0
+    if (!info)
28add0
+	return NULL;
28add0
+
28add0
+    info->next = image_table[hash % HASH_SIZE];
28add0
+    image_table[hash % HASH_SIZE] = info;
28add0
+    
28add0
+    return info;
28add0
+}
28add0
+
28add0
+static void
28add0
+remove_image_info (image_info_t *info)
28add0
+{
28add0
+    struct image_info_t **location = &image_table[info->image->descriptor.id % HASH_SIZE];
28add0
+
28add0
+    while (*location && (*location) != info)
28add0
+	location = &((*location)->next);
28add0
+
28add0
+    if (*location)
28add0
+	*location = info->next;
28add0
+
28add0
+    free (info);
28add0
+}
28add0
+
28add0
+struct qxl_image *
28add0
+qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
28add0
+		  int x, int y, int width, int height,
28add0
+		  int stride)
28add0
+{
28add0
+    unsigned int hash;
28add0
+    image_info_t *info;
28add0
+
28add0
+    data += y * stride + x * qxl->bytes_per_pixel;
28add0
+
28add0
+    hash = hash_and_copy (data, stride, NULL, -1, qxl->bytes_per_pixel, width, height);
28add0
+
28add0
+    info = lookup_image_info (hash, width, height);
28add0
+    if (info)
28add0
+    {
28add0
+	int i, j;
28add0
+	
28add0
+#if 0
28add0
+	ErrorF ("reusing image %p with hash %u (%d x %d)\n", info->image, hash, width, height);
28add0
+#endif
28add0
+	
28add0
+	info->ref_count++;
28add0
+
28add0
+	for (i = 0; i < height; ++i)
28add0
+	{
28add0
+	    struct qxl_data_chunk *chunk;
28add0
+	    const uint8_t *src_line = data + i * stride;
28add0
+	    uint32_t *dest_line;
28add0
+		
28add0
+	    chunk = virtual_address (qxl, u64_to_pointer (info->image->u.bitmap.data));
28add0
+	    
28add0
+	    dest_line = (uint32_t *)chunk->data + width * i;
28add0
+
28add0
+	    for (j = 0; j < width; ++j)
28add0
+	    {
28add0
+		uint32_t *s = (uint32_t *)src_line;
28add0
+		uint32_t *d = (uint32_t *)dest_line;
28add0
+		
28add0
+		if (d[j] != s[j])
28add0
+		{
28add0
+#if 0
28add0
+		    ErrorF ("bad collision at (%d, %d)! %d != %d\n", j, i, s[j], d[j]);
28add0
+#endif
28add0
+		    goto out;
28add0
+		}
28add0
+	    }
28add0
+	}
28add0
+    out:
28add0
+	return info->image;
28add0
+    }
28add0
+    else
28add0
+    {
28add0
+	struct qxl_image *image;
28add0
+	struct qxl_data_chunk *chunk;
28add0
+	int dest_stride = width * qxl->bytes_per_pixel;
28add0
+	image_info_t *info;
28add0
+
28add0
+#if 0
28add0
+	ErrorF ("Must create new image of size %d %d\n", width, height);
28add0
+#endif
28add0
+	
28add0
+	/* Chunk */
28add0
+	
28add0
+	/* FIXME: Check integer overflow */
28add0
+	chunk = qxl_allocnf (qxl, sizeof *chunk + height * dest_stride);
28add0
+	
28add0
+	chunk->data_size = height * dest_stride;
28add0
+	chunk->prev_chunk = 0;
28add0
+	chunk->next_chunk = 0;
28add0
+	
28add0
+	hash_and_copy (data, stride,
28add0
+		       chunk->data, dest_stride,
28add0
+		       qxl->bytes_per_pixel, width, height);
28add0
+
28add0
+	/* Image */
28add0
+	image = qxl_allocnf (qxl, sizeof *image);
28add0
+
28add0
+	image->descriptor.id = 0;
28add0
+	image->descriptor.type = QXL_IMAGE_TYPE_BITMAP;
28add0
+	
28add0
+	image->descriptor.flags = 0;
28add0
+	image->descriptor.width = width;
28add0
+	image->descriptor.height = height;
28add0
+
28add0
+	if (qxl->bytes_per_pixel == 2)
28add0
+	{
28add0
+	    image->u.bitmap.format = QXL_BITMAP_FMT_16BIT;
28add0
+	}
28add0
+	else
28add0
+	{
28add0
+	    image->u.bitmap.format = QXL_BITMAP_FMT_32BIT;
28add0
+	}
28add0
+
28add0
+	image->u.bitmap.flags = QXL_BITMAP_TOP_DOWN;
28add0
+	image->u.bitmap.x = width;
28add0
+	image->u.bitmap.y = height;
28add0
+	image->u.bitmap.stride = width * qxl->bytes_per_pixel;
28add0
+	image->u.bitmap.palette = 0;
28add0
+	image->u.bitmap.data = physical_address (qxl, chunk);
28add0
+
28add0
+#if 0
28add0
+	ErrorF ("%p has size %d %d\n", image, width, height);
28add0
+#endif
28add0
+	
28add0
+	/* Add to hash table */
28add0
+	if ((info = insert_image_info (hash)))
28add0
+	{
28add0
+	    info->image = image;
28add0
+	    info->ref_count = 1;
28add0
+
28add0
+	    image->descriptor.id = hash;
28add0
+	    image->descriptor.flags = QXL_IMAGE_CACHE;
28add0
+
28add0
+#if 0
28add0
+	    ErrorF ("added with hash %u\n", hash);
28add0
+#endif
28add0
+	}
28add0
+
28add0
+	return image;
28add0
+    }
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_image_destroy (qxl_screen_t *qxl,
28add0
+		   struct qxl_image *image)
28add0
+{
28add0
+    struct qxl_data_chunk *chunk;
28add0
+    image_info_t *info;
28add0
+
28add0
+    chunk = virtual_address (qxl, u64_to_pointer (image->u.bitmap.data));
28add0
+    
28add0
+    info = lookup_image_info (image->descriptor.id,
28add0
+			      image->descriptor.width,
28add0
+			      image->descriptor.height);
28add0
+
28add0
+    if (info && info->image == image)
28add0
+    {
28add0
+	--info->ref_count;
28add0
+
28add0
+	if (info->ref_count != 0)
28add0
+	    return;
28add0
+
28add0
+#if 0
28add0
+	ErrorF ("removed %p from hash table\n", info->image);
28add0
+#endif
28add0
+	
28add0
+	remove_image_info (info);
28add0
+    }
28add0
+
28add0
+    qxl_free (qxl->mem, chunk);
28add0
+    qxl_free (qxl->mem, image);
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_drop_image_cache (qxl_screen_t *qxl)
28add0
+{
28add0
+    memset (image_table, 0, HASH_SIZE * sizeof (image_info_t *));
28add0
+}
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-qxl_mem.c.compat xf86-video-qxl-20130514/src/compat/compat-qxl_mem.c
28add0
--- xf86-video-qxl-20130514/src/compat/compat-qxl_mem.c.compat	2013-07-03 14:18:57.096319282 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-qxl_mem.c	2013-07-03 14:18:57.096319282 +1000
28add0
@@ -0,0 +1,321 @@
28add0
+#include <assert.h>
28add0
+#include <stdio.h>
28add0
+#include <stdlib.h>
28add0
+
28add0
+#include "compat-qxl.h"
28add0
+
28add0
+struct block
28add0
+{
28add0
+    unsigned long n_bytes;
28add0
+    
28add0
+    union
28add0
+    {
28add0
+	struct
28add0
+	{
28add0
+	    struct block *next;
28add0
+	} unused;
28add0
+
28add0
+	struct
28add0
+	{
28add0
+	    uint8_t data[0];
28add0
+	} used;
28add0
+    } u;
28add0
+};
28add0
+
28add0
+struct qxl_mem
28add0
+{
28add0
+    void *		base;
28add0
+    unsigned long	n_bytes;
28add0
+    
28add0
+    struct block *unused;
28add0
+    unsigned long total_allocated;
28add0
+    unsigned long total_freed;
28add0
+    unsigned long n_allocated_blocks;
28add0
+    unsigned long n_freed_blocks;
28add0
+};
28add0
+
28add0
+static void
28add0
+initialize (struct qxl_mem *mem)
28add0
+{
28add0
+    mem->unused = (struct block *)mem->base;
28add0
+    mem->unused->n_bytes = mem->n_bytes;
28add0
+    mem->unused->u.unused.next = NULL;    
28add0
+
28add0
+    mem->total_allocated = 0;
28add0
+    mem->total_freed = 0;
28add0
+    mem->n_allocated_blocks = 0;
28add0
+    mem->n_freed_blocks = 0;
28add0
+}
28add0
+
28add0
+struct qxl_mem *
28add0
+qxl_mem_create (void *base, unsigned long n_bytes)
28add0
+{
28add0
+    struct qxl_mem *mem = NULL;
28add0
+
28add0
+    mem = calloc (sizeof (*mem), 1);
28add0
+    if (!mem)
28add0
+	goto out;
28add0
+
28add0
+    mem->base = base;
28add0
+    mem->n_bytes = n_bytes;
28add0
+
28add0
+    initialize (mem);
28add0
+    
28add0
+out:
28add0
+    return mem;
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_mem_free_all (struct qxl_mem *mem)
28add0
+{
28add0
+    initialize (mem);
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_mem_dump_stats (struct qxl_mem *mem, const char *header)
28add0
+{
28add0
+    struct block *b;
28add0
+    int n_blocks;
28add0
+    unsigned long max_block = 0;
28add0
+    unsigned long min_block = 0xffffffffffffffffUL;
28add0
+    
28add0
+    fprintf (stderr, "%s\n", header);
28add0
+    
28add0
+    n_blocks = 0;
28add0
+    for (b = mem->unused; b != NULL; b = b->u.unused.next)
28add0
+    {
28add0
+	fprintf (stderr, "block: %p (%lu bytes)\n", b, b->n_bytes);
28add0
+	
28add0
+	if (b->u.unused.next && b >= b->u.unused.next)
28add0
+	{
28add0
+	    fprintf (stderr, "b: %p   b->next: %p\n",
28add0
+		     b, b->u.unused.next);
28add0
+	    assert (0);
28add0
+	}
28add0
+
28add0
+	if (b->u.unused.next && (void *)b + b->n_bytes >= b->u.unused.next)
28add0
+	{
28add0
+	    fprintf (stderr, "OVERLAPPING BLOCKS b: %p   b->next: %p\n",
28add0
+		     b, b->u.unused.next);
28add0
+	    assert (0);
28add0
+	}
28add0
+
28add0
+	if (b->n_bytes > max_block)
28add0
+	    max_block = b->n_bytes;
28add0
+
28add0
+	if (b->n_bytes < min_block)
28add0
+	    min_block = b->n_bytes;
28add0
+	
28add0
+	++n_blocks;
28add0
+    }
28add0
+
28add0
+    fprintf (stderr, "=========\n");
28add0
+
28add0
+    fprintf (stderr, "%d blocks\n", n_blocks);
28add0
+    fprintf (stderr, "min block: %lu bytes\n", min_block);
28add0
+    fprintf (stderr, "max block: %lu bytes\n", max_block);
28add0
+    fprintf (stderr, "total freed: %lu bytres\n", mem->total_freed);
28add0
+    fprintf (stderr, "total allocated: %lu bytes\n",
28add0
+	     mem->total_allocated - mem->total_freed);
28add0
+    fprintf (stderr, "total free: %lu bytes\n",
28add0
+	     mem->n_bytes - (mem->total_allocated - mem->total_freed));
28add0
+}
28add0
+
28add0
+void *
28add0
+qxl_alloc (struct qxl_mem *mem, unsigned long n_bytes)
28add0
+{
28add0
+    struct block *b, *prev;
28add0
+
28add0
+    mem->n_allocated_blocks++;
28add0
+    
28add0
+    /* Simply pretend the user asked to allocate the header as well. Then
28add0
+     * we can mostly ignore the difference between blocks and allocations
28add0
+     */
28add0
+    n_bytes += sizeof (unsigned long);
28add0
+
28add0
+    n_bytes = (n_bytes + 7) & ~((1 << 3) - 1);
28add0
+    
28add0
+    if (n_bytes < sizeof (struct block))
28add0
+	n_bytes = sizeof (struct block);
28add0
+
28add0
+    assert (mem->unused);
28add0
+    
28add0
+    prev = NULL;
28add0
+    for (b = mem->unused; b != NULL; prev = b, b = b->u.unused.next)
28add0
+    {
28add0
+	if (b->n_bytes >= n_bytes)
28add0
+	{
28add0
+	    struct block *new_block;
28add0
+
28add0
+	    if (b->n_bytes - n_bytes >= sizeof (struct block))
28add0
+	    {
28add0
+		new_block = (void *)b + n_bytes;
28add0
+
28add0
+		new_block->n_bytes = b->n_bytes - n_bytes;
28add0
+
28add0
+		if (prev)
28add0
+		{
28add0
+		    assert (prev < b);
28add0
+		    assert (prev->u.unused.next == NULL || prev < prev->u.unused.next);
28add0
+		    
28add0
+ 		    new_block->u.unused.next = b->u.unused.next;
28add0
+		    prev->u.unused.next = new_block;
28add0
+		}
28add0
+		else
28add0
+		{
28add0
+		    assert (mem->unused == b);
28add0
+
28add0
+		    new_block->u.unused.next = mem->unused->u.unused.next;
28add0
+		    mem->unused = new_block;
28add0
+		}
28add0
+
28add0
+		b->n_bytes = n_bytes;
28add0
+	    }
28add0
+	    else
28add0
+	    {
28add0
+#if 0
28add0
+		printf ("Exact match\n");
28add0
+#endif
28add0
+
28add0
+		if (prev)
28add0
+		{
28add0
+		    prev->u.unused.next = b->u.unused.next;
28add0
+		}
28add0
+		else
28add0
+		{
28add0
+		    mem->unused = b->u.unused.next;
28add0
+		}
28add0
+	    }
28add0
+
28add0
+	    mem->total_allocated += n_bytes;
28add0
+	    
28add0
+	    return (void *)b->u.used.data;
28add0
+	}
28add0
+	else
28add0
+	{
28add0
+#if 0
28add0
+	    printf ("Skipping small block %d\n", b->n_bytes);
28add0
+#endif
28add0
+	}
28add0
+    }
28add0
+
28add0
+    /* If we get here, we are out of memory, so print some stats */
28add0
+#if 0
28add0
+    fprintf (stderr, "Failing to allocate %lu bytes\n", n_bytes);
28add0
+    qxl_mem_dump_stats (mem, "out of memory");
28add0
+#endif
28add0
+    
28add0
+    return NULL;
28add0
+}
28add0
+
28add0
+/* Finds the unused block before and the unused block after @data. Both
28add0
+ * before and after can be NULL if data is before the first or after the
28add0
+ * last unused block.
28add0
+ */
28add0
+static void
28add0
+find_neighbours (struct qxl_mem *mem, void *data,
28add0
+		 struct block **before, struct block **after)
28add0
+{
28add0
+    struct block *b;
28add0
+    *before = NULL;
28add0
+    *after = NULL;
28add0
+    
28add0
+    for (b = mem->unused; b != NULL; b = b->u.unused.next)
28add0
+    {
28add0
+	if ((void *)b < data)
28add0
+	    *before = b;
28add0
+	
28add0
+	if ((void *)b > data)
28add0
+	{
28add0
+	    *after = b;
28add0
+	    break;
28add0
+	}
28add0
+    }
28add0
+
28add0
+    if (*before)
28add0
+	assert ((*before)->u.unused.next == *after);
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_free (struct qxl_mem *mem, void *d)
28add0
+{
28add0
+    struct block *b = d - sizeof (unsigned long);
28add0
+    struct block *before, *after;
28add0
+
28add0
+    mem->total_freed += b->n_bytes;
28add0
+    mem->n_freed_blocks++;
28add0
+    
28add0
+#if 0
28add0
+    printf ("freeing %p (%d bytes)\n", b, b->n_bytes);
28add0
+    
28add0
+    qxl_mem_dump_stats (mem, "before free");
28add0
+#endif
28add0
+    
28add0
+    find_neighbours (mem, (void *)b, &before, &after);
28add0
+
28add0
+    if (before)
28add0
+    {
28add0
+#if 0
28add0
+	printf ("  free: merge before: %p\n", before->u.used.data);
28add0
+#endif
28add0
+	    
28add0
+	if ((void *)before + before->n_bytes == b)
28add0
+	{
28add0
+#if 0
28add0
+ 	    printf ("  free: merge with before (adding %d bytes)\n", b->n_bytes);
28add0
+#endif
28add0
+	    
28add0
+	    /* Merge before and b */
28add0
+	    before->n_bytes += b->n_bytes;
28add0
+	    b = before;
28add0
+	}
28add0
+	else
28add0
+	{
28add0
+#if 0
28add0
+	    printf ("  free: no merge with before\n");
28add0
+#endif
28add0
+	    
28add0
+	    before->u.unused.next = b;
28add0
+	}
28add0
+    }
28add0
+    else
28add0
+    {
28add0
+#if 0
28add0
+	printf ("  free: no before\n");
28add0
+#endif
28add0
+	mem->unused = b;
28add0
+    }
28add0
+    
28add0
+    if (after)
28add0
+    {
28add0
+#if 0
28add0
+	printf ("  free: after: %p\n", after->u.used.data);
28add0
+#endif
28add0
+	if ((void *)b + b->n_bytes == after)
28add0
+	{
28add0
+#if 0
28add0
+	    printf ("  merge with after\n");
28add0
+#endif
28add0
+	    b->n_bytes += after->n_bytes;
28add0
+	    b->u.unused.next = after->u.unused.next;
28add0
+	}
28add0
+	else
28add0
+	{
28add0
+#if 0
28add0
+	    printf ("  no merge with after\n");
28add0
+#endif
28add0
+	    b->u.unused.next = after;
28add0
+ 	}
28add0
+    }
28add0
+    else
28add0
+    {
28add0
+#if 0
28add0
+	printf ("  free: no after\n");
28add0
+#endif
28add0
+	b->u.unused.next = NULL;
28add0
+    }
28add0
+
28add0
+#if 0
28add0
+    qxl_mem_dump_stats (mem, "after free");
28add0
+#endif
28add0
+}
28add0
diff -up xf86-video-qxl-20130514/src/compat/compat-qxl_ring.c.compat xf86-video-qxl-20130514/src/compat/compat-qxl_ring.c
28add0
--- xf86-video-qxl-20130514/src/compat/compat-qxl_ring.c.compat	2013-07-03 14:18:57.096319282 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/compat-qxl_ring.c	2013-07-03 14:18:57.096319282 +1000
28add0
@@ -0,0 +1,97 @@
28add0
+#include <string.h>
28add0
+#include <unistd.h>
28add0
+#include <stdlib.h>
28add0
+#include "compat-qxl.h"
28add0
+
28add0
+struct ring
28add0
+{
28add0
+    struct qxl_ring_header	header;
28add0
+    uint8_t			elements[0];
28add0
+};
28add0
+
28add0
+struct qxl_ring
28add0
+{
28add0
+    volatile struct ring *ring;
28add0
+    int			element_size;
28add0
+    int			n_elements;
28add0
+    int			prod_notify;
28add0
+};
28add0
+
28add0
+struct qxl_ring *
28add0
+qxl_ring_create (struct qxl_ring_header *header,
28add0
+		 int                     element_size,
28add0
+		 int                     n_elements,
28add0
+		 int			 prod_notify)
28add0
+{
28add0
+    struct qxl_ring *ring;
28add0
+
28add0
+    ring = malloc (sizeof *ring);
28add0
+    if (!ring)
28add0
+	return NULL;
28add0
+
28add0
+    ring->ring = (volatile struct ring *)header;
28add0
+    ring->element_size = element_size;
28add0
+    ring->n_elements = n_elements;
28add0
+    ring->prod_notify = prod_notify;
28add0
+    
28add0
+    return ring;
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_ring_push (struct qxl_ring *ring,
28add0
+	       const void      *new_elt)
28add0
+{
28add0
+    volatile struct qxl_ring_header *header = &(ring->ring->header);
28add0
+    volatile uint8_t *elt;
28add0
+    int idx;
28add0
+
28add0
+    while (header->prod - header->cons == header->num_items)
28add0
+    {
28add0
+	header->notify_on_cons = header->cons + 1;
28add0
+
28add0
+	mem_barrier();
28add0
+    }
28add0
+
28add0
+    idx = header->prod & (ring->n_elements - 1);
28add0
+    elt = ring->ring->elements + idx * ring->element_size;
28add0
+
28add0
+    memcpy((void *)elt, new_elt, ring->element_size);
28add0
+
28add0
+    header->prod++;
28add0
+
28add0
+    mem_barrier();
28add0
+
28add0
+    if (header->prod == header->notify_on_prod)
28add0
+	outb (ring->prod_notify, 0);
28add0
+}
28add0
+
28add0
+Bool
28add0
+qxl_ring_pop (struct qxl_ring *ring,
28add0
+	      void            *element)
28add0
+{
28add0
+    volatile struct qxl_ring_header *header = &(ring->ring->header);
28add0
+    volatile uint8_t *ring_elt;
28add0
+    int idx;
28add0
+
28add0
+    if (header->cons == header->prod)
28add0
+	return FALSE;
28add0
+
28add0
+    idx = header->cons & (ring->n_elements - 1);
28add0
+    ring_elt = ring->ring->elements + idx * ring->element_size;
28add0
+
28add0
+    memcpy (element, (void *)ring_elt, ring->element_size);
28add0
+
28add0
+    header->cons++;
28add0
+
28add0
+    return TRUE;
28add0
+}
28add0
+
28add0
+void
28add0
+qxl_ring_wait_idle (struct qxl_ring *ring)
28add0
+{
28add0
+    while (ring->ring->header.cons != ring->ring->header.prod)
28add0
+    {
28add0
+	usleep (1000);
28add0
+	mem_barrier();
28add0
+    }
28add0
+}
28add0
diff -up xf86-video-qxl-20130514/src/compat/Makefile.am.compat xf86-video-qxl-20130514/src/compat/Makefile.am
28add0
--- xf86-video-qxl-20130514/src/compat/Makefile.am.compat	2013-07-03 14:18:57.093319209 +1000
28add0
+++ xf86-video-qxl-20130514/src/compat/Makefile.am	2013-07-03 14:18:57.093319209 +1000
28add0
@@ -0,0 +1,41 @@
28add0
+#  Copyright 2008 Red Hat, Inc.
28add0
+#
28add0
+#  Permission is hereby granted, free of charge, to any person obtaining a
28add0
+#  copy of this software and associated documentation files (the "Software"),
28add0
+#  to deal in the Software without restriction, including without limitation
28add0
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
28add0
+#  license, and/or sell copies of the Software, and to permit persons to whom
28add0
+#  the Software is furnished to do so, subject to the following conditions:
28add0
+#
28add0
+#  The above copyright notice and this permission notice (including the next
28add0
+#  paragraph) shall be included in all copies or substantial portions of the
28add0
+#  Software.
28add0
+#
28add0
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28add0
+#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28add0
+#  FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
28add0
+#  THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
28add0
+#  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28add0
+#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28add0
+
28add0
+
28add0
+# this is obnoxious:
28add0
+# -module lets us name the module exactly how we want
28add0
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
28add0
+# _ladir passes a dummy rpath to libtool so the thing will actually link
28add0
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
28add0
+qxl_drv_la_LTLIBRARIES = qxl_drv.la
28add0
+qxl_drv_la_LDFLAGS = -module -avoid-version
28add0
+qxl_drv_ladir = @moduledir@/drivers
28add0
+AM_CFLAGS = -g
28add0
+AM_CFLAGS = $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS)
28add0
+
28add0
+qxl_drv_la_SOURCES =				\
28add0
+	compat-qxl.h					\
28add0
+	compat-qxl_driver.c				\
28add0
+	compat-qxl_image.c				\
28add0
+	compat-qxl_ring.c				\
28add0
+	compat-qxl_mem.c				\
28add0
+	compat-lookup3.c				\
28add0
+	compat-lookup3.h				\
28add0
+	compat-qxl_cursor.c
28add0
diff -up xf86-video-qxl-20130514/src/Makefile.am.compat xf86-video-qxl-20130514/src/Makefile.am
28add0
--- xf86-video-qxl-20130514/src/Makefile.am.compat	2013-07-03 14:18:40.381914397 +1000
28add0
+++ xf86-video-qxl-20130514/src/Makefile.am	2013-07-03 14:18:57.093319209 +1000
28add0
@@ -25,7 +25,7 @@
28add0
 # _ladir passes a dummy rpath to libtool so the thing will actually link
28add0
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
28add0
 
28add0
-SUBDIRS=uxa
28add0
+SUBDIRS=uxa compat
28add0
 
28add0
 AM_CFLAGS = $(SPICE_PROTOCOL_CFLAGS) $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(DRM_CFLAGS) @LIBUDEV_CFLAGS@
28add0