From: Egbert Eich <eich@suse.de>
Date: Wed Jan 21 11:32:58 2015 +0100
Subject: [PATCH]Backport to Xserver 1.6.5
Patch-mainline: never

References: FATE#318098
Signed-off-by: Egbert Eich <eich@suse.com>

Signed-off-by: Egbert Eich <eich@suse.de>
---
 src/dfps.c           |  27 ++---
 src/list.h           | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/qxl.h            |   7 ++
 src/qxl_driver.c     |   7 ++
 src/qxl_surface.c    |   4 +-
 src/qxl_uxa.c        |   5 +-
 src/uxa/uxa-render.c |  17 +---
 src/uxa/uxa.c        |   4 +
 8 files changed, 319 insertions(+), 33 deletions(-)

diff --git a/src/dfps.c b/src/dfps.c
index 568ba5e..776839b 100644
--- a/src/dfps.c
+++ b/src/dfps.c
@@ -109,6 +109,7 @@ void dfps_ticker(void *opaque)
     qxl_screen_t *qxl = (qxl_screen_t *) opaque;
     dfps_info_t *info = NULL;
     PixmapPtr pixmap;
+    BoxPtr dummy = NULL;
 
     pixmap = qxl->pScrn->pScreen->GetScreenPixmap(qxl->pScrn->pScreen);
     if (pixmap)
@@ -116,8 +117,8 @@ void dfps_ticker(void *opaque)
     if (info)
     {
         qxl_surface_upload_primary_regions(qxl, pixmap, &info->updated_region);
-        RegionUninit(&info->updated_region);
-        RegionInit(&info->updated_region, NULL, 0);
+        REGION_UNINIT(NULL, &info->updated_region);
+        REGION_INIT(NULL, &info->updated_region, dummy, 0);
     }
     timer_start(qxl->frames_timer, 1000 / qxl->deferred_fps);
 }
@@ -141,14 +142,15 @@ static void dfps_update_box(RegionPtr dest, int x_1, int x_2, int y_1, int y_2);
 static void dfps_update_region(RegionPtr dest, RegionPtr src)
 {
     Bool throwaway_bool;
+    BoxPtr dummy = NULL;
 
-    RegionAppend(dest, src);
-    RegionValidate(dest, &throwaway_bool);
-    if (RegionNumRects(dest) > DFPS_MAX_UPDATE_REGIONS)
+    REGION_APPEND(NULL, dest, src);
+    REGION_VALIDATE(NULL, dest, &throwaway_bool);
+    if (REGION_NUM_RECTS(dest) > DFPS_MAX_UPDATE_REGIONS)
     {
-        struct pixman_box16 box = * (RegionExtents(dest));
-        RegionUninit(dest);
-        RegionInit(dest, NULL, 0);
+	struct pixman_box16 box = * (REGION_EXTENTS(NULL, dest));
+        REGION_UNINIT(NULL, dest);
+        REGION_INIT(pScreen, dest, dummy, 0);
         dfps_update_box(dest, box.x1, box.x2, box.y1, box.y2);
     }
 }
@@ -159,12 +161,12 @@ static void dfps_update_box(RegionPtr dest, int x_1, int x_2, int y_1, int y_2)
     RegionPtr region;
 
     box.x1 = x_1; box.x2 = x_2; box.y1 = y_1; box.y2 = y_2;
-    region = RegionCreate(&box, 1);
+    region = REGION_CREATE(NULL, &box, 1);
 
     dfps_update_region(dest, region);
 
-    RegionUninit(region);
-    RegionDestroy(region);
+    REGION_UNINIT(NULL, region);
+    REGION_DESTROY(NULL, region);
 }
 
 static Bool dfps_prepare_solid (PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
@@ -327,11 +329,12 @@ static PixmapPtr dfps_create_pixmap (ScreenPtr screen, int w, int h, int depth,
 {
     PixmapPtr pixmap;
     dfps_info_t *info;
+    BoxPtr dummy = NULL;
 
     info = calloc(1, sizeof(*info));
     if (!info)
         return FALSE;
-    RegionInit(&info->updated_region, NULL, 0);
+    REGION_INIT(NULL, &info->updated_region, dummy, 0);
 
     pixmap = fbCreatePixmap (screen, w, h, depth, usage);
     if (pixmap)
diff --git a/src/list.h b/src/list.h
new file mode 100644
index 0000000..5933b97
--- /dev/null
+++ b/src/list.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ * Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _LIST_H_
+#define _LIST_H_
+
+/**
+ * @file Classic doubly-link circular list implementation.
+ *
+ * Example:
+ * We need to keep a list of struct foo in the parent struct bar, i.e. what
+ * we want is something like this.
+ *
+ *     struct bar {
+ *          ...
+ *          struct foo *foos; -----> struct foo {}, struct foo {}, struct foo{}
+ *          ...
+ *     }
+ *
+ * We need one list head in bar and a list element in all foos (both are of
+ * data type 'struct list').
+ *
+ *     struct bar {
+ *          ...
+ *          struct list foos;
+ *          ...
+ *     }
+ *
+ *     struct foo {
+ *          ...
+ *          struct list entry;
+ *          ...
+ *     }
+ *
+ * Now we initialize the list head:
+ *
+ *     struct bar bar;
+ *     ...
+ *     list_init(&bar.foos);
+ *
+ * Then we create the first element and add it to this list:
+ *
+ *     struct foo *foo = malloc(...);
+ *     ....
+ *     list_add(&foo->entry, &bar.foos);
+ *
+ * Repeat the above for each element you want to add to the list. Deleting
+ * works with the element itself.
+ *      list_del(&foo->entry);
+ *      free(foo);
+ *
+ * Note: calling list_del(&bar.foos) will set bar.foos to an empty
+ * list again.
+ *
+ * Looping through the list requires a 'struct foo' as iterator and the
+ * name of the field the subnodes use.
+ *
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar.foos, entry) {
+ *      if (iterator->something == ...)
+ *             ...
+ * }
+ *
+ * Note: You must not call list_del() on the iterator if you continue the
+ * loop. You need to run the safe for-each loop instead:
+ *
+ * struct foo *iterator, *next;
+ * list_for_each_entry_safe(iterator, next, &bar.foos, entry) {
+ *      if (...)
+ *              list_del(&iterator->entry);
+ * }
+ *
+ */
+
+/**
+ * The linkage struct for list nodes. This struct must be part of your
+ * to-be-linked struct.
+ *
+ * Example:
+ * struct foo {
+ *      int a;
+ *      void *b;
+ *      struct list *mylist;
+ * }
+ *
+ * Position and name of the struct list field is irrelevant.
+ * There are no requirements that elements of a list are of the same type.
+ * There are no requirements for a list head, any struct list can be a list
+ * head.
+ */
+struct list {
+    struct list *next, *prev;
+};
+
+/**
+ * Initialize the list as an empty list.
+ *
+ * Example:
+ * list_init(&foo->mylist);
+ *
+ * @param The list to initialized.
+ */
+static void
+list_init(struct list *list)
+{
+    list->next = list->prev = list;
+}
+
+static inline void
+__list_add(struct list *entry,
+	    struct list *prev,
+	    struct list *next)
+{
+    next->prev = entry;
+    entry->next = next;
+    entry->prev = prev;
+    prev->next = entry;
+}
+
+/**
+ * Insert a new element after the given list head.
+ * The list changes from:
+ *      head → some element → ...
+ * to
+ *      head → new element → older element → ...
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add(&newfoo->mylist, &foo->mylist);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add(struct list *entry, struct list *head)
+{
+    __list_add(entry, head, head->next);
+}
+
+static inline void
+__list_del(struct list *prev, struct list *next)
+{
+    next->prev = prev;
+    prev->next = next;
+}
+
+/**
+ * Remove the element from the list it is in. Using this function will reset
+ * the pointers to/from this element so it is removed from the list. It does
+ * NOT free the element itself or manipulate it otherwise.
+ *
+ * Using list_del on a pure list head (like in the example at the top of
+ * this file) will NOT remove the first element from
+ * the list but rather reset the list as empty list.
+ *
+ * Example:
+ * list_del(&newfoo->mylist);
+ *
+ * @param entry The element to remove.
+ */
+static inline void
+list_del(struct list *entry)
+{
+    __list_del(entry->prev, entry->next);
+    list_init(entry);
+}
+
+/**
+ * Check if the list is empty.
+ *
+ * Example:
+ * list_is_empty(&foo->mylist);
+ *
+ * @return True if the list contains one or more elements or False otherwise.
+ */
+static inline Bool
+list_is_empty(struct list *head)
+{
+    return head->next == head;
+}
+
+/**
+ * Returns a pointer to the container of this list element.
+ *
+ * Example:
+ * struct foo* f;
+ * f = container_of(&foo->mylist, struct foo, mylist);
+ * assert(f == foo);
+ *
+ * @param ptr Pointer to the struct list.
+ * @param type Data type of the list element.
+ * @param member Member name of the struct list field in the list element.
+ * @return A pointer to the data struct containing the list head.
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) \
+    (type *)((char *)(ptr) - (char *) &((type *)0)->member)
+#endif
+
+/**
+ * Alias of container_of
+ */
+#define list_entry(ptr, type, member) \
+    container_of(ptr, type, member)
+
+/**
+ * Retrieve the first list entry for the given list pointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_first_entry(&foo->mylist, struct foo, mylist);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list field in the list element.
+ * @return A pointer to the first list element.
+ */
+#define list_first_entry(ptr, type, member) \
+    list_entry((ptr)->next, type, member)
+
+#define __container_of(ptr, sample, member)				\
+    (void *)((char *)(ptr)						\
+	     - ((char *)&(sample)->member - (char *)(sample)))
+/**
+ * Loop through the list given by head and set pos to struct in the list.
+ *
+ * Example:
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &foo->mylist, mylist) {
+ *      [modify iterator]
+ * }
+ *
+ * This macro is not safe for node deletion. Use list_for_each_entry_safe
+ * instead.
+ *
+ * @param pos Iterator variable of the type of the list elements.
+ * @param head List head
+ * @param member Member name of the struct list in the list elements.
+ *
+ */
+#define list_for_each_entry(pos, head, member)				\
+    for (pos = __container_of((head)->next, pos, member);		\
+	 &pos->member != (head);					\
+	 pos = __container_of(pos->member.next, pos, member))
+
+/**
+ * Loop through the list, keeping a backup pointer to the element. This
+ * macro allows for the deletion of a list element while looping through the
+ * list.
+ *
+ * See list_for_each_entry for more details.
+ */
+#define list_for_each_entry_safe(pos, tmp, head, member)		\
+    for (pos = __container_of((head)->next, pos, member),		\
+	 tmp = __container_of(pos->member.next, pos, member);		\
+	 &pos->member != (head);					\
+	 pos = tmp, tmp = __container_of(pos->member.next, tmp, member))
+
+#endif
diff --git a/src/qxl.h b/src/qxl.h
index 603faca..c402501 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -668,5 +668,12 @@ SpiceServer *xspice_get_spice_server(void);
 #define CHECK_POINT()
 #endif
 
+#define fbGetPixmapBitsData(pixmap, pointer, stride, bpp) { \
+	(pointer) = (FbBits *) (pixmap)->devPrivate.ptr; \
+	(stride) = ((int) (pixmap)->devKind) / sizeof (FbBits); \
+	(void)(stride); \
+	(bpp) = (pixmap)->drawable.bitsPerPixel; \
+	(void)(bpp); \
+	}
 
 #endif // QXL_H
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index 072953c..079e6a5 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -39,6 +39,7 @@
 #include <time.h>
 #include <stdlib.h>
 
+#include <X11/Xmd.h>
 #include <xf86Crtc.h>
 #include <xf86RandR12.h>
 
@@ -782,7 +783,11 @@ qxl_screen_init (SCREEN_INIT_ARGS_DECL)
        as the privates size is not computed correctly until then
      */
 #if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 12, 99, 901, 0))
+# if (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 8, 99, 901, 0))
     pScreen->totalPixmapSize = BitmapBytePad ((sizeof (PixmapRec) + dixPrivatesSize (PRIVATE_PIXMAP) ) * 8);
+# else
+    pScreen->totalPixmapSize = BitmapBytePad(sizeof(PixmapRec)*8);
+# endif
 #else
     pScreen->totalPixmapSize = BitmapBytePad((sizeof(PixmapRec) +
 			    dixScreenSpecificPrivatesSize(pScreen, PRIVATE_PIXMAP) ) * 8);
@@ -1476,7 +1481,9 @@ static DriverRec qxl_driver = {
 #ifdef XSERVER_PLATFORM_BUS
     qxl_platform_probe,
 #else
+# if (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 12, 99, 901, 0))
     NULL,
+# endif
 #endif
 #endif /* XSPICE */
 };
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index c5e76e0..64b1159 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -332,8 +332,8 @@ qxl_surface_upload_primary_regions(qxl_screen_t *qxl, PixmapPtr pixmap, RegionRe
     int n_boxes;
     BoxPtr boxes;
 
-    n_boxes = RegionNumRects(r);
-    boxes = RegionRects(r);
+    n_boxes = REGION_NUM_RECTS(r);
+    boxes = REGION_RECTS(r);
 
     while (n_boxes--)
     {
diff --git a/src/qxl_uxa.c b/src/qxl_uxa.c
index 875d663..0ba6545 100644
--- a/src/qxl_uxa.c
+++ b/src/qxl_uxa.c
@@ -299,10 +299,7 @@ qxl_check_composite (int op,
 	PictOpClear, PictOpSrc, PictOpDst, PictOpOver, PictOpOverReverse,
 	PictOpIn, PictOpInReverse, PictOpOut, PictOpOutReverse,
 	PictOpAtop, PictOpAtopReverse, PictOpXor, PictOpAdd,
-	PictOpSaturate, PictOpMultiply, PictOpScreen, PictOpOverlay,
-	PictOpDarken, PictOpLighten, PictOpColorDodge, PictOpColorBurn,
-	PictOpHardLight, PictOpSoftLight, PictOpDifference, PictOpExclusion,
-	PictOpHSLHue, PictOpHSLSaturation, PictOpHSLColor, PictOpHSLLuminosity,
+	PictOpSaturate,
     };
 
     if (!qxl_has_composite (qxl))
diff --git a/src/uxa/uxa-render.c b/src/uxa/uxa-render.c
index 937ac2e..899c998 100644
--- a/src/uxa/uxa-render.c
+++ b/src/uxa/uxa-render.c
@@ -34,6 +34,8 @@
 #ifdef RENDER
 #include "mipict.h"
 
+#define PICT_TYPE_BGRA               PIXMAN_TYPE_BGRA
+
 static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string,
 					     int n)
 {
@@ -137,21 +139,6 @@ op_to_string(CARD8 op)
 	/*
 	 * Operators only available in version 0.11
 	 */
-	C(Multiply);
-	C(Screen);
-	C(Overlay);
-	C(Darken);
-	C(Lighten);
-	C(ColorDodge);
-	C(ColorBurn);
-	C(HardLight);
-	C(SoftLight);
-	C(Difference);
-	C(Exclusion);
-	C(HSLHue);
-	C(HSLSaturation);
-	C(HSLColor);
-	C(HSLLuminosity);
     default: return "garbage";
 #undef C
     }
diff --git a/src/uxa/uxa.c b/src/uxa/uxa.c
index 36d610e..15a7682 100644
--- a/src/uxa/uxa.c
+++ b/src/uxa/uxa.c
@@ -509,6 +509,10 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
 #if HAS_DIXREGISTERPRIVATEKEY
         if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
             return FALSE;
+#else
+	if (!dixRequestPrivate(&uxa_screen_index, 0))
+	    return FALSE;
+
 #endif
 	uxa_screen = calloc(sizeof(uxa_screen_t), 1);
 
