[Spice-commits] 4 commits - display/brush.c display/driver.c display/quic.c display/quic_config.h display/quic_family_tmpl.c display/quic.h display/quic_rgb_tmpl.c display/quic_tmpl.c display/qxldd.h display/res.c display/res.h display/rop.c display/surface.c display/surface.h display/text.c include/qxl_driver.h include/stdint.h

Alexander Larsson alexl at kemper.freedesktop.org
Wed Feb 17 02:14:51 PST 2010


 display/brush.c            |   10 
 display/driver.c           |   17 
 display/quic.c             | 1715 ++++++++++++++++++++++++++++++++++++++++++++-
 display/quic.h             |   64 +
 display/quic_config.h      |   50 +
 display/quic_family_tmpl.c |  114 ++
 display/quic_rgb_tmpl.c    |  762 +++++++++++++++++++
 display/quic_tmpl.c        |  632 ++++++++++++++++
 display/qxldd.h            |   14 
 display/res.c              |  617 ++++++++++++----
 display/res.h              |   24 
 display/rop.c              |  280 +++++--
 display/surface.c          |    2 
 display/surface.h          |    2 
 display/text.c             |    6 
 include/qxl_driver.h       |    4 
 include/stdint.h           |  394 ++++++++++
 17 files changed, 4478 insertions(+), 229 deletions(-)

New commits:
commit 43d86f9e38436d07066cf667ee4ed0b94d54a28c
Author: Izik Eidus <ieidus at redhat.com>
Date:   Tue Feb 16 21:35:57 2010 +0200

    do guest driver to host memcpys using sse.
    
    Just copy chunks of data in sse2 instrcutions with prefeching of cache
    bytes. - 35%~ cpu improvment when playing video in windows.
    
    The first code that I wrote for this patch actuly handled
    all the algiment requirment in the spice qxl win driver,
    and did all the copys in 16 bytes algiment,
    however due requiments from libspice server the cost of maitaing 16byte algiment
    for each "line of copy" is too high and therefore whenever we better use
    unalgiment copys whenever the bitmaps arent already 16byte algiment.
    
    There is alot of space for improvment in this patch, but due to
    timelines and the fact that we have another hurry tasks I will just push
    this patch for now - the results are very good right now
    
    Thanks.
    
    Signed-off-by: Izik Eidus <ieidus at redhat.com>

diff --git a/display/driver.c b/display/driver.c
index a8ef9f0..b723bf5 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -240,6 +240,7 @@ BOOL DrvEnableDriver(ULONG engine_version, ULONG enable_data_size, PDRVENABLEDAT
     mspace_set_abort_func(mspace_abort);
     mspace_set_print_func(mspace_print);
     ResInitGlobals();
+    CheckAndSetSSE2();
     InitGlobalRes();
     DEBUG_PRINT((NULL, 1, "%s: end\n", __FUNCTION__));
     return TRUE;
diff --git a/display/qxldd.h b/display/qxldd.h
index bff84d1..80dd30a 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -184,6 +184,9 @@ typedef struct DevRes {
 #endif
 } DevRes;
 
+#define SSE_MASK 15
+#define SSE_ALIGN 16
+
 typedef struct PDev {
     HANDLE driver;
     HDEV eng;
@@ -268,6 +271,8 @@ typedef struct PDev {
 
     Ring update_trace;
     UpdateTrace update_trace_items[NUM_UPDATE_TRACE_ITEMS];
+
+    UINT8 FPUSave[16 * 4 + 15];
 } PDev;
 
 
diff --git a/display/res.c b/display/res.c
index 2b0735a..a358351 100644
--- a/display/res.c
+++ b/display/res.c
@@ -90,6 +90,8 @@ typedef struct QXLOutput {
     UINT8 data[0];
 } QXLOutput;
 
+static int have_sse2 = FALSE;
+
 
 UINT64 ReleaseOutput(PDev *pdev, UINT64 output_id)
 {
@@ -798,26 +800,229 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable)
     return TRUE;
 }
 
+static _inline void fast_memcpy_aligment(void *dest, const void *src, size_t len)
+{
+    _asm
+    {
+        mov ecx, len
+        mov esi, src
+        mov edi, dest
+
+        cmp ecx, 128
+        jb try_to_copy64
+ 
+        prefetchnta [esi]
+        copy_128:
+            prefetchnta [esi + 64]
+
+            movdqa xmm0, [esi]
+            movdqa xmm1, [esi + 16]
+            movdqa xmm2, [esi + 32]
+            movdqa xmm3, [esi + 48]
+
+            prefetchnta [esi + 128]
+
+            movntdq [edi], xmm0
+            movntdq [edi + 16], xmm1
+            movntdq [edi + 32], xmm2
+            movntdq [edi + 48], xmm3
+
+            movdqa xmm0, [esi + 64]
+            movdqa xmm1, [esi + 80]
+            movdqa xmm2, [esi + 96]
+            movdqa xmm3, [esi + 112]
+
+            movntdq [edi + 64], xmm0
+            movntdq [edi + 80], xmm1
+            movntdq [edi + 96], xmm2
+            movntdq [edi + 112], xmm3
+
+            add edi, 128
+            add esi, 128
+            sub ecx, 128
+            cmp ecx, 128
+            jae copy_128
+ 
+       try_to_copy64:
+            cmp ecx, 64
+            jb try_to_copy32
+
+             movdqa xmm0, [esi]
+             movdqa xmm1, [esi + 16]
+             movdqa xmm2, [esi + 32]
+             movdqa xmm3, [esi + 48]
+
+             movntdq [edi], xmm0
+             movntdq [edi + 16], xmm1
+             movntdq [edi + 32], xmm2
+             movntdq [edi + 48], xmm3
+             
+             add edi, 64
+             add esi, 64
+             sub ecx, 64
+             prefetchnta [esi]
+
+        try_to_copy32:
+             cmp ecx, 32
+             jb try_to_copy16
+
+             movdqa xmm0, [esi]
+             movdqa xmm1, [esi + 16] 
+             movntdq [edi], xmm0
+             movntdq [edi + 16], xmm1
+
+             add edi, 32 
+             add esi, 32 
+             sub ecx, 32
+
+        try_to_copy16:
+             cmp ecx, 16
+             jb try_to_copy4
+
+             movdqa xmm0, [esi]
+             movntdq [edi], xmm0
+
+             add edi, 16
+             add esi, 16
+             sub ecx, 16
+
+
+        try_to_copy4:
+            cmp ecx, 4
+            jb try_to_copy_1 
+            movsd
+            sub ecx, 4
+            jmp try_to_copy4
+
+        try_to_copy_1:     
+            rep movsb
+
+        sfence
+    }
+}
+
+static _inline void fast_memcpy_unaligment(void *dest, const void *src, size_t len)
+{
+    _asm
+    {
+        mov ecx, len
+        mov esi, src
+        mov edi, dest
+
+        cmp ecx, 128
+        jb try_to_copy64
+ 
+        prefetchnta [esi]
+        copy_128:
+            prefetchnta [esi + 64]
+
+            movdqu xmm0, [esi]
+            movdqu xmm1, [esi + 16]
+            movdqu xmm2, [esi + 32]
+            movdqu xmm3, [esi + 48]
+
+            prefetchnta [esi + 128]
+
+            movntdq [edi], xmm0
+            movntdq [edi + 16], xmm1
+            movntdq [edi + 32], xmm2
+            movntdq [edi + 48], xmm3
+
+            movdqu xmm0, [esi + 64]
+            movdqu xmm1, [esi + 80]
+            movdqu xmm2, [esi + 96]
+            movdqu xmm3, [esi + 112]
+
+            movntdq [edi + 64], xmm0
+            movntdq [edi + 80], xmm1
+            movntdq [edi + 96], xmm2
+            movntdq [edi + 112], xmm3
+
+            add edi, 128
+            add esi, 128
+            sub ecx, 128
+            cmp ecx, 128
+            jae copy_128
+ 
+       try_to_copy64:
+            cmp ecx, 64
+            jb try_to_copy32
+
+             movdqu xmm0, [esi]
+             movdqu xmm1, [esi + 16]
+             movdqu xmm2, [esi + 32]
+             movdqu xmm3, [esi + 48]
+
+             movntdq [edi], xmm0
+             movntdq [edi + 16], xmm1
+             movntdq [edi + 32], xmm2
+             movntdq [edi + 48], xmm3
+             
+             add edi, 64
+             add esi, 64
+             sub ecx, 64
+             prefetchnta [esi]
+
+        try_to_copy32:
+             cmp ecx, 32
+             jb try_to_copy16
+
+             movdqu xmm0, [esi]
+             movdqu xmm1, [esi + 16] 
+             movntdq [edi], xmm0
+             movntdq [edi + 16], xmm1
+
+             add edi, 32 
+             add esi, 32 
+             sub ecx, 32
+
+        try_to_copy16:
+             cmp ecx, 16
+             jb try_to_copy4
+
+             movdqu xmm0, [esi]
+             movntdq [edi], xmm0
+
+             add edi, 16
+             add esi, 16
+             sub ecx, 16
+
+
+        try_to_copy4:
+            cmp ecx, 4
+            jb try_to_copy_1 
+            movsd
+            sub ecx, 4
+            jmp try_to_copy4
+
+        try_to_copy_1:     
+            rep movsb
+
+        sfence
+    }
+}
+
 #ifdef DBG
     #define PutBytesAlign __PutBytesAlign
-    #define PutBytes(pdev, chunk, now, end, src, size, page_counter, alloc_size)\
-    __PutBytesAlign(pdev, chunk, now, end, src, size, page_counter, alloc_size, 1)
+#define PutBytes(pdev, chunk, now, end, src, size, page_counter, alloc_size, use_sse)\
+    __PutBytesAlign(pdev, chunk, now, end, src, size, page_counter, alloc_size, 1, use_sse)
 #else
-    #define  PutBytesAlign(pdev, chunk, now, end, src, size, page_counter, alloc_size, alignment)\
-    __PutBytesAlign(pdev, chunk, now, end, src, size, NULL, alloc_size, alignment)
-    #define  PutBytes(pdev, chunk, now, end, src, size, page_counter, alloc_size)\
-    __PutBytesAlign(pdev, chunk, now, end, src, size, NULL, alloc_size, 1)
+#define  PutBytesAlign(pdev, chunk, now, end, src, size, page_counter, alloc_size, alignment, use_sse)\
+    __PutBytesAlign(pdev, chunk, now, end, src, size, NULL, alloc_size, alignment, use_sse)
+#define  PutBytes(pdev, chunk, now, end, src, size, page_counter, alloc_size, use_sse)\
+    __PutBytesAlign(pdev, chunk, now, end, src, size, NULL, alloc_size, 1, use_sse)
 #endif
 
 #define BITS_BUF_MAX (64 * 1024)
 
 static void __PutBytesAlign(PDev *pdev, QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
                             UINT8 **end_ptr, UINT8 *src, int size, int *page_counter,
-                            size_t alloc_size, uint32_t alignment)
+                            size_t alloc_size, uint32_t alignment, BOOL use_sse)
 {
     QXLDataChunk *chunk = *chunk_ptr;
     UINT8 *now = *now_ptr;
     UINT8 *end = *end_ptr;
+    int offset;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     while (size) {
@@ -831,7 +1036,35 @@ static void __PutBytesAlign(PDev *pdev, QXLDataChunk **chunk_ptr, UINT8 **now_pt
             NEW_DATA_CHUNK(page_counter, aligned_size);
             cp_size = MIN(end - now, size);
         }
-        RtlCopyMemory(now, src, cp_size);
+
+        if (use_sse) {
+            offset = (size_t)now & SSE_MASK;
+            if (offset) {
+                offset = SSE_ALIGN - offset;
+                if (offset >= cp_size) {
+                    RtlCopyMemory(now, src, cp_size);
+                    src += cp_size;
+                    now += cp_size;
+                    chunk->data_size += cp_size;
+                    size -= cp_size;
+                    continue;
+                }
+                RtlCopyMemory(now, src,  offset);
+                now += offset;
+                src += offset;
+                size -= offset;
+                cp_size -= offset;
+                chunk->data_size += offset;
+            }
+    
+            if (((size_t)src & SSE_MASK) == 0) {
+                fast_memcpy_aligment(now, src, cp_size);
+            } else {
+                fast_memcpy_unaligment(now, src, cp_size);
+            }
+        } else {
+            RtlCopyMemory(now, src, cp_size);
+        }
         src += cp_size;
         now += cp_size;
         chunk->data_size += cp_size;
@@ -1270,6 +1503,36 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
 
+static _inline void RestoreFPU(PDev *pdev)
+{
+    void *align_addr =  (void *)ALIGN((size_t)(&pdev->FPUSave), SSE_ALIGN);
+
+    _asm
+    {
+        mov esi, align_addr
+
+        movdqa xmm0, [esi]
+        movdqa xmm1, [esi + 16]
+        movdqa xmm2, [esi + 32]
+        movdqa xmm3, [esi + 48]
+    }
+}
+
+static _inline void SaveFPU(PDev *pdev)
+{
+    void *align_addr =  (void *)ALIGN((size_t)(&pdev->FPUSave), SSE_ALIGN);
+
+    _asm
+    {
+        mov edi, align_addr
+    
+        movdqa [edi], xmm0
+        movdqa [edi + 16], xmm1
+        movdqa [edi + 32], xmm2
+        movdqa [edi + 48], xmm3
+    }
+}
+
 #define BITMAP_ALLOC_BASE (sizeof(Resource) + sizeof(InternalImage) + sizeof(QXLDataChunk))
 
 static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans,
@@ -1283,6 +1546,7 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
     UINT8 *src_end;
     UINT8 *dest;
     UINT8 *dest_end;
+    BOOL use_sse = FALSE;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     ASSERT(pdev, width > 0 && height > 0);
@@ -1314,9 +1578,19 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
     dest = chunk->data;
     dest_end = (UINT8 *)image_res + alloc_size;
     alloc_size = height * line_size;
+
+    if (have_sse2 && alloc_size >= 1024) {
+        use_sse = TRUE;
+        SaveFPU(pdev);
+    }
+
     for (; src != src_end; src -= surf->lDelta, alloc_size -= line_size) {
         PutBytesAlign(pdev, &chunk, &dest, &dest_end, src, line_size,
-                      &pdev->Res.num_bits_pages, alloc_size, line_size);
+                      &pdev->Res.num_bits_pages, alloc_size, line_size, TRUE);
+    }
+
+    if (use_sse) {
+        RestoreFPU(pdev);
     }
 
     GetPallette(pdev, &internal->image.bitmap, color_trans);
@@ -2357,7 +2631,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
     src_end = src + (surf->lDelta * surf->sizlBitmap.cy);
     for (; src != src_end; src += surf->lDelta) {
         PutBytes(pdev, &info->chunk, &info->now, &info->end, src, line_size,
-                 &pdev->Res.num_cursor_pages, PAGE_SIZE);
+                 &pdev->Res.num_cursor_pages, PAGE_SIZE, FALSE);
     }
 
     CursorCacheAdd(pdev, internal);
@@ -2454,14 +2728,14 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
             if (pdev->bitmap_format == BMF_32BPP) {
                 PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)color_trans->pulXlate,
-                         256 << 2, &pdev->Res.num_cursor_pages, PAGE_SIZE);
+                         256 << 2, &pdev->Res.num_cursor_pages, PAGE_SIZE, FALSE);
             } else {
                 int i;
 
                 for (i = 0; i < 256; i++) {
                     UINT32 ent = _16bppTo32bpp(color_trans->pulXlate[i]);
                     PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)&ent,
-                             4, &pdev->Res.num_cursor_pages, PAGE_SIZE);
+                             4, &pdev->Res.num_cursor_pages, PAGE_SIZE, FALSE);
                 }
             }
             info.cursor->data_size += 256 << 2;
@@ -2474,14 +2748,14 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
             if (pdev->bitmap_format == BMF_32BPP) {
                 PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)color_trans->pulXlate,
-                         16 << 2, &pdev->Res.num_cursor_pages, PAGE_SIZE);
+                         16 << 2, &pdev->Res.num_cursor_pages, PAGE_SIZE, FALSE);
             } else {
                 int i;
 
                 for (i = 0; i < 16; i++) {
                     UINT32 ent = _16bppTo32bpp(color_trans->pulXlate[i]);
                     PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)&ent,
-                             4, &pdev->Res.num_cursor_pages, PAGE_SIZE);
+                             4, &pdev->Res.num_cursor_pages, PAGE_SIZE, FALSE);
                 }
             }
             info.cursor->data_size += 16 << 2;
@@ -2493,7 +2767,7 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
         for (; src != src_end; src += mask->lDelta) {
             PutBytes(pdev, &info.chunk, &info.now, &info.end, src, line_size,
-                     &pdev->Res.num_cursor_pages, PAGE_SIZE);
+                     &pdev->Res.num_cursor_pages, PAGE_SIZE, FALSE);
         }
     }
 
@@ -2614,3 +2888,20 @@ void ResDestroyGlobals()
     image_id_sem = NULL;
 }
 
+void CheckAndSetSSE2()
+{
+    _asm
+    {
+        mov eax, 0x0000001
+        cpuid
+        and edx, 0x4000000
+        mov have_sse2, edx
+    }
+
+    if (have_sse2) {
+        have_sse2 = TRUE;
+    }
+}
+
+
+
diff --git a/display/res.h b/display/res.h
index e181434..5af8a26 100644
--- a/display/res.h
+++ b/display/res.h
@@ -56,4 +56,5 @@ BOOL ResInit(PDev *pdev);
 void ResDestroy(PDev *pdev);
 void ResInitGlobals();
 void ResDestroyGlobals();
+void CheckAndSetSSE2();
 #endif
commit ad5433a6b33ec59954601f0b7dbacc4609a4f754
Author: Izik Eidus <ieidus at redhat.com>
Date:   Tue Feb 16 20:55:43 2010 +0200

    qxl: add counter for stream_test
    
    It fix some issues with WAN and applications such as
    powerpoint that its slides can be wrongly thought as
    a video streaming in the driver and therefore not to get
    cached.
    
    Thanks
    
    Signed-off-by: Izik Eidus <ieidus at redhat.com>

diff --git a/display/qxldd.h b/display/qxldd.h
index a69c264..bff84d1 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -133,6 +133,7 @@ typedef struct UpdateTrace {
     UINT32 last_time;
     RECTL area;
     HSURF hsurf;
+    UINT8 count;
 } UpdateTrace;
 
 typedef struct PMemSlot {
diff --git a/display/rop.c b/display/rop.c
index 746dd6a..83efdd3 100644
--- a/display/rop.c
+++ b/display/rop.c
@@ -484,11 +484,17 @@ static BOOL StreamTest(PDev *pdev, SURFOBJ *src_surf, XLATEOBJ *color_trans, REC
             BOOL ret;
 
             if (now != trace->last_time && now - trace->last_time < 1000 / 5) {
-                ret = FALSE;
                 trace->last_time = now - 1; // asumong mm clock is active so delta t == 0 is
                                             // imposibole. frocing delata t to be at least 1.
+                if (trace->count < 20) {
+                    trace->count++;
+                    ret = TRUE;
+                } else {
+                    ret = FALSE;
+                }
             } else {
                 trace->last_time = now;
+                trace->count = 0;
                 ret = TRUE;
             }
             RingRemove(pdev, (RingItem *)trace);
@@ -509,6 +515,7 @@ static BOOL StreamTest(PDev *pdev, SURFOBJ *src_surf, XLATEOBJ *color_trans, REC
     } else {
         trace->hsurf = NULL;
     }
+    trace->count = 0;
     RingAdd(pdev, ring, (RingItem *)trace);
 
     return TRUE;
commit a7fb50d6c2395c32b236e42eac84b79be653c2cb
Author: Izik Eidus <ieidus at redhat.com>
Date:   Tue Feb 16 20:30:14 2010 +0200

    spice: split heavily clipped images into small images (speed win7)
    
    This really speed up windows 7
    
    Thanks
    
    Signed-off-by: Izik Eidus <ieidus at redhat.com>

diff --git a/display/res.c b/display/res.c
index 4b1a2fd..2b0735a 100644
--- a/display/res.c
+++ b/display/res.c
@@ -890,7 +890,6 @@ static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
     while (cache_image) {
         if (cache_image->key == key && (!check_rest || (cache_image->format == format &&
             cache_image->width == width && cache_image->height == height))) {
-            cache_image->hits++;
             return cache_image;
         }
         cache_image = cache_image->next;
@@ -1411,16 +1410,10 @@ static BOOL ChachSizeTest(PDev *pdev, SURFOBJ *surf)
     return ret;
 }
 
-
-static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans, UINT32 *hash_key)
+static _inline UINT64 get_unique(SURFOBJ *surf, XLATEOBJ *color_trans)
 {
-    CacheImage *cache_image;
-    ULONG pallette_unique;
-    UINT64 gdi_unique;
     int pallette;
-    UINT32 key;
-    UINT8 format;
-    UINT32 line_size;
+    ULONG pallette_unique;
 
     pallette = color_trans && (color_trans->flXlate & XO_TABLE);
     pallette_unique = pallette ? color_trans->iUniq : 0;
@@ -1428,11 +1421,65 @@ static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
     // NOTE: GDI sometimes gives many instances of the exactly same SURFOBJ (hsurf & iUniq),
     // but with (fjBitmap & BMF_DONTCACHE). This opposed to what documented in the MSDN.
     if (!surf->iUniq || (surf->fjBitmap & BMF_DONTCACHE) || (pallette && !pallette_unique)) {
-        gdi_unique = 0;
+        return 0;
     } else {
-        gdi_unique = surf->iUniq | ((UINT64)pallette_unique << 32);
+        return (surf->iUniq | ((UINT64)pallette_unique << 32));
+    }
+}
+
+BOOL CheckIfCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans)
+{
+    CacheImage *cache_image;
+    UINT64 gdi_unique;
+    UINT32 key;
+    UINT8 format;
+
+    gdi_unique = get_unique(surf, color_trans);
+
+    if (!ImageKeyGet(pdev, surf->hsurf, gdi_unique, &key)) {
+        return FALSE;
+    }
+
+    switch (surf->iBitmapFormat) {
+    case BMF_32BPP:
+        format = SPICE_BITMAP_FMT_32BIT;
+        break;
+    case BMF_24BPP:
+        format = SPICE_BITMAP_FMT_24BIT;
+        break;
+    case BMF_16BPP:
+        format = SPICE_BITMAP_FMT_16BIT;
+        break;
+    case BMF_8BPP:
+        format = SPICE_BITMAP_FMT_8BIT;
+        break;
+    case BMF_4BPP:
+        format = SPICE_BITMAP_FMT_4BIT_BE;
+        break;
+    case BMF_1BPP:
+        format = SPICE_BITMAP_FMT_1BIT_BE;
+    }
+
+
+    if ((cache_image = ImageCacheGetByKey(pdev, key, TRUE, format,
+                                          surf->sizlBitmap.cx,
+                                          surf->sizlBitmap.cy))) {
+        return TRUE;
     }
 
+    return FALSE;
+}
+
+static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans, UINT32 *hash_key)
+{
+    CacheImage *cache_image;
+    UINT64 gdi_unique;
+    UINT32 key;
+    UINT8 format;
+    UINT32 line_size;
+
+    gdi_unique = get_unique(surf, color_trans);
+
     if (!(line_size = GetFormatLineSize(surf->sizlBitmap.cx, surf->iBitmapFormat, &format))) {
         DEBUG_PRINT((pdev, 0, "%s: bitmap format err\n", __FUNCTION__));
         return FALSE;
@@ -1454,6 +1501,7 @@ static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
     if ((cache_image = ImageCacheGetByKey(pdev, key, TRUE, format,
                                           surf->sizlBitmap.cx,
                                           surf->sizlBitmap.cy))) {
+        cache_image->hits++;
         DEBUG_PRINT((pdev, 11, "%s: ImageCacheGetByKey %u hits %u\n", __FUNCTION__,
                      key, cache_image->hits));
         return cache_image;
@@ -1653,6 +1701,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
                                          surf->sizlBitmap.cx, surf->sizlBitmap.cy)) {
         DEBUG_PRINT((pdev, 11, "%s: ImageCacheGetByKey %u hits %u\n", __FUNCTION__,
                      key, cache_image->hits));
+        cache_image->hits++;
         if (internal = cache_image->image) {
             DEBUG_PRINT((pdev, 11, "%s: cached image found %u\n", __FUNCTION__, key));
             *image_phys = PA(pdev, &internal->image, pdev->main_mem_slot);
@@ -1712,6 +1761,7 @@ BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, QXL
 
     if ((cache_image = ImageCacheGetByKey(pdev, hash_key, FALSE, 0, 0, 0)) &&
         (internal = cache_image->image)) {
+        cache_image->hits++;
         *image_phys = PA(pdev, &internal->image, pdev->main_mem_slot);
         image_res = (Resource *)((UINT8 *)internal - sizeof(Resource));
         DrawableAddRes(pdev, drawable, image_res);
diff --git a/display/res.h b/display/res.h
index bc18d1f..e181434 100644
--- a/display/res.h
+++ b/display/res.h
@@ -37,6 +37,7 @@ BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SU
 BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, QXLPHYSICAL *image_phys);
 BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SURFOBJ *surf,
                        SpiceRect *area);
+BOOL CheckIfCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans);
 UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *buf_phys, UINT32 size);
 BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *str_phys, FONTOBJ *font, STROBJ *str);
 
diff --git a/display/rop.c b/display/rop.c
index b9b25b8..746dd6a 100644
--- a/display/rop.c
+++ b/display/rop.c
@@ -514,6 +514,96 @@ static BOOL StreamTest(PDev *pdev, SURFOBJ *src_surf, XLATEOBJ *color_trans, REC
     return TRUE;
 }
 
+static BOOL TestSplitClips(PDev *pdev, RECTL *src_rect, CLIPOBJ *clip, SURFOBJ *mask)
+{
+    UINT32 width;
+    UINT32 height;
+    UINT32 src_space;
+    UINT32 clip_space = 0;
+    int more;
+
+    if (!clip || mask) {
+        return FALSE;
+    }
+
+    width = src_rect->right - src_rect->left;
+    height = src_rect->bottom - src_rect->top;
+    src_space = width * height;
+
+    if (clip->iDComplexity == DC_RECT) {
+        width = clip->rclBounds.right - clip->rclBounds.left;
+        height = clip->rclBounds.bottom - clip->rclBounds.top;
+        clip_space = width * height;
+
+        if ((src_space / clip_space) > 1) {
+            return TRUE;
+        }
+        return FALSE;
+    }
+
+    if (clip->iMode == TC_RECTANGLES) {
+        CLIPOBJ_cEnumStart(clip, TRUE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
+        do {
+            RECTL *now;
+            RECTL *end;
+
+            struct {
+                ULONG  count;
+                RECTL  rects[20];
+            } buf;
+
+            more = CLIPOBJ_bEnum(clip, sizeof(buf), (ULONG *)&buf);
+            for(now = buf.rects, end = now + buf.count; now < end; now++) {
+                width = now->right - now->left;
+                height = now->bottom - now->top;
+                clip_space += width * height;
+            }
+        } while (more);
+
+        if ((src_space / clip_space) > 1) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static _inline BOOL DoPartialCopy(PDev *pdev, SURFOBJ *src, RECTL *src_rect, RECTL *area_rect,
+                                  RECTL *clip_rect, XLATEOBJ *color_trans, ULONG scale_mode,
+                                  UINT16 rop_decriptor)
+{
+    QXLDrawable *drawable;
+    RECTL clip_area;
+
+    SectRect(area_rect, clip_rect, &clip_area);
+    if (IsEmptyRect(&clip_area)) {
+        return TRUE;
+    }
+
+    if (!(drawable = Drawable(pdev, QXL_DRAW_COPY, &clip_area, NULL))) {
+        return FALSE;
+    }
+
+    drawable->effect = QXL_EFFECT_OPAQUE;
+    drawable->u.copy.scale_mode = GdiScaleModeToQxl(scale_mode);
+    drawable->u.copy.mask.bitmap = 0;
+    drawable->u.copy.rop_decriptor = rop_decriptor;
+
+    drawable->u.copy.src_area.top = src_rect->top + (clip_area.top - area_rect->top);
+    drawable->u.copy.src_area.bottom = drawable->u.copy.src_area.top + clip_area.bottom -
+                                       clip_area.top;
+    drawable->u.copy.src_area.left = src_rect->left + (clip_area.left - area_rect->left);
+    drawable->u.copy.src_area.right = drawable->u.copy.src_area.left + clip_area.right -
+                                      clip_area.left;
+
+    if(!GetBitmap(pdev, drawable, &drawable->u.copy.src_bitmap, src, &drawable->u.copy.src_area,
+                  color_trans, FALSE)) {
+        ReleaseOutput(pdev, drawable->release_info.id);
+        return FALSE;
+    }
+    PushDrawable(pdev, drawable);
+    return TRUE;
+}
+
 static BOOL DoCopy(PDev *pdev, RECTL *area, CLIPOBJ *clip, SURFOBJ *src, RECTL *src_rect,
                    XLATEOBJ *color_trans, UINT16 rop_decriptor, SURFOBJ *mask, POINTL *mask_pos,
                    BOOL invers_mask, ULONG scale_mode)
@@ -524,16 +614,52 @@ static BOOL DoCopy(PDev *pdev, RECTL *area, CLIPOBJ *clip, SURFOBJ *src, RECTL *
     ASSERT(pdev, pdev && area && src_rect && src);
     DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
 
+    if (mask) {
+        use_cache = TRUE;
+    } else {
+        use_cache = StreamTest(pdev, src, color_trans, src_rect, area);
+    }
+
+    if (use_cache && TestSplitClips(pdev, src_rect, clip, mask) &&
+        !CheckIfCacheImage(pdev, src, color_trans)) {
+
+        if (clip->iDComplexity == DC_RECT) {
+            if (!DoPartialCopy(pdev, src, src_rect, area, &clip->rclBounds, color_trans, scale_mode,
+                               rop_decriptor)) {
+                return FALSE;
+            }
+        } else {
+            int more;
+            ASSERT(pdev, clip->iMode == TC_RECTANGLES);
+            CLIPOBJ_cEnumStart(clip, TRUE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
+            do {
+                RECTL *now;
+                RECTL *end;
+
+                struct {
+                    ULONG  count;
+                    RECTL  rects[20];
+                } buf;
+                more = CLIPOBJ_bEnum(clip, sizeof(buf), (ULONG *)&buf);
+                for(now = buf.rects, end = now + buf.count; now < end; now++) {
+                    if (!DoPartialCopy(pdev, src, src_rect, area, now, color_trans, scale_mode,
+                                       rop_decriptor)) {
+                        return FALSE;
+                    }
+                }
+            } while (more);
+        }
+        return TRUE;
+    }
+
     if (!(drawable = Drawable(pdev, QXL_DRAW_COPY, area, clip))) {
         return FALSE;
     }
 
     if (mask) {
         drawable->effect = QXL_EFFECT_BLEND;
-        use_cache = TRUE;
     } else {
         drawable->effect = QXL_EFFECT_OPAQUE;
-        use_cache = StreamTest(pdev, src, color_trans, src_rect, area);
     }
 
     drawable->u.copy.scale_mode = GdiScaleModeToQxl(scale_mode);
commit 3dbe9ce052efd576ff883436793403ab0c9d0757
Author: Izik Eidus <ieidus at redhat.com>
Date:   Tue Feb 16 19:46:49 2010 +0200

    qxl win: make the qxl driver build with latest namespace changes
    
    No logic change, just bunch of black work.
    
    Signed-off-by: Izik Eidus <ieidus at redhat.com>

diff --git a/display/brush.c b/display/brush.c
index 6105487..802c0a9 100644
--- a/display/brush.c
+++ b/display/brush.c
@@ -314,12 +314,12 @@ BOOL APIENTRY DrvRealizeBrush(BRUSHOBJ *brush, SURFOBJ *target, SURFOBJ *pattern
 }
 
 
-static _inline BOOL GetPattern(PDev *pdev, QXLDrawable *drawable, PHYSICAL *pattern,
+static _inline BOOL GetPattern(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *pattern,
                                InternalBrush *brush)
 {
     HSURF hsurf;
     SURFOBJ *surf_obj;
-    Rect area;
+    SpiceRect area;
     UINT32 key;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
@@ -360,7 +360,7 @@ error_1:
 }
 
 
-BOOL QXLGetBrush(PDev *pdev, QXLDrawable *drawable, Brush *qxl_brush,
+BOOL QXLGetBrush(PDev *pdev, QXLDrawable *drawable, SpiceBrush *qxl_brush,
                             BRUSHOBJ *brush, POINTL *brush_pos)
 {
     DEBUG_PRINT((pdev, 9, "%s\n", __FUNCTION__));
@@ -374,14 +374,14 @@ BOOL QXLGetBrush(PDev *pdev, QXLDrawable *drawable, Brush *qxl_brush,
             DEBUG_PRINT((pdev, 0, "%s: brush realize failed\n", __FUNCTION__));
             return FALSE;
         }
-        qxl_brush->type = BRUSH_TYPE_PATTERN;
+        qxl_brush->type = SPICE_BRUSH_TYPE_PATTERN;
         qxl_brush->u.pattern.pos.x = brush_pos->x;
         qxl_brush->u.pattern.pos.y = brush_pos->y;
         if (!GetPattern(pdev, drawable, &qxl_brush->u.pattern.pat, brush->pvRbrush)) {
             return FALSE;
         }
     } else {
-        qxl_brush->type = BRUSH_TYPE_SOLID;
+        qxl_brush->type = SPICE_BRUSH_TYPE_SOLID;
         qxl_brush->u.color = brush->iSolidColor;
         DEBUG_PRINT((pdev, 11, "%s: color 0x%x\n", __FUNCTION__, qxl_brush->u.color));
     }
diff --git a/display/driver.c b/display/driver.c
index 2a66683..a8ef9f0 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -570,7 +570,7 @@ static VOID HideMouse(PDev *pdev)
 }
 
 static VOID CreatePrimarySurface(PDev *pdev, UINT32 depth, UINT32 width, UINT32 height,
-                                 PHYSICAL phys_mem)
+                                 QXLPHYSICAL phys_mem)
 {
     pdev->primary_surface_create->depth = depth;
     pdev->primary_surface_create->width = width;
@@ -610,7 +610,7 @@ BOOL SetHardwareMode(PDev *pdev)
 
 static VOID UpdateMainSlot(PDev *pdev, MemSlot *slot)
 {
-    ADDRESS high_bits;
+    SPICE_ADDRESS high_bits;
 
 
     pdev->mem_slots[pdev->main_mem_slot].slot = *slot;
@@ -620,7 +620,7 @@ static VOID UpdateMainSlot(PDev *pdev, MemSlot *slot)
     high_bits <<= (64 - (pdev->slot_gen_bits + pdev->slot_id_bits));
     pdev->mem_slots[pdev->main_mem_slot].high_bits = high_bits;
 
-    pdev->va_slot_mask = (~(PHYSICAL)0) >> (pdev->slot_id_bits + pdev->slot_gen_bits);
+    pdev->va_slot_mask = (~(QXLPHYSICAL)0) >> (pdev->slot_id_bits + pdev->slot_gen_bits);
 }
 
 BOOL PrepareHardware(PDev *pdev)
@@ -629,7 +629,7 @@ BOOL PrepareHardware(PDev *pdev)
     VIDEO_MEMORY_INFORMATION video_mem_Info;
     DWORD length;
     QXLDriverInfo dev_info;
-    ADDRESS high_bits;
+    SPICE_ADDRESS high_bits;
 
     DEBUG_PRINT((NULL, 1, "%s: 0x%lx\n", __FUNCTION__, pdev));
 
@@ -774,7 +774,7 @@ HSURF DrvEnableSurface(DHPDEV in_pdev)
     PDev *pdev;
     HSURF surf;
     DWORD length;
-    PHYSICAL phys_mem;
+    QXLPHYSICAL phys_mem;
     UINT8 *base_mem;
     DrawArea drawarea;
 
@@ -1026,7 +1026,7 @@ FIX FlotaToFixed(FLOATL val, FLOATL scale)
     return ret;
 }
 
-static BOOL GetGeometricAttr(PDev *pdev, QXLDrawable *drawable, LineAttr *q_line_attr,
+static BOOL GetGeometricAttr(PDev *pdev, QXLDrawable *drawable, SpiceLineAttr *q_line_attr,
                             LINEATTRS *line_attr, XFORMOBJ *width_transform)
 {
     ULONG save_buf_size;
@@ -1119,7 +1119,7 @@ err1:
     return FALSE;
 }
 
-static BOOL GetCosmeticAttr(PDev *pdev, QXLDrawable *drawable, LineAttr *q_line_attr,
+static BOOL GetCosmeticAttr(PDev *pdev, QXLDrawable *drawable, SpiceLineAttr *q_line_attr,
                             LINEATTRS *line_attr)
 {
     ASSERT(pdev, LINE_CAP_ROUND == ENDCAP_ROUND && LINE_CAP_SQUARE == ENDCAP_SQUARE &&
@@ -1224,7 +1224,7 @@ BOOL APIENTRY DrvStrokePath(SURFOBJ *surf, PATHOBJ *path, CLIPOBJ *clip, XFORMOB
     back_rop = &rops2[((mix >> 8) - 1) & 0x0f];
 
     if (!((fore_rop->flags | back_rop->flags) & ROP3_BRUSH)) {
-        drawable->u.stroke.brush.type = BRUSH_TYPE_NONE;
+        drawable->u.stroke.brush.type = SPICE_BRUSH_TYPE_NONE;
     } else if (!QXLGetBrush(pdev, drawable, &drawable->u.stroke.brush, brush, brush_pos)) {
         goto err;
     }
diff --git a/display/quic.c b/display/quic.c
index 848d6d9..1e0bbee 100644
--- a/display/quic.c
+++ b/display/quic.c
@@ -15,4 +15,1717 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "..\common\quic.c"
+// Red Hat image compression based on SFALIC by Roman Starosolski
+// http://sun.iinf.polsl.gliwice.pl/~rstaros/sfalic/index.html
+
+#include "stddef.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "os_dep.h"
+
+#include "winerror.h"
+#include "windef.h"
+#include "wingdi.h"
+#include "winddi.h"
+#include "devioctl.h"
+#include "ntddvdeo.h"
+#include "ioaccess.h"
+
+#include "qxldd.h"
+#include "utils.h"
+#include "mspace.h"
+#include "res.h"
+#include "surface.h"
+
+
+#include "quic.h"
+
+//#define DEBUG
+
+#define RLE
+#define RLE_STAT
+#define PRED_1
+//#define RLE_PRED_1
+#define RLE_PRED_2
+//#define RLE_PRED_3
+#define QUIC_RGB
+
+#define QUIC_MAGIC (*(uint32_t *)"QUIC")
+#define QUIC_VERSION_MAJOR 0U
+#define QUIC_VERSION_MINOR 1U
+#define QUIC_VERSION ((QUIC_VERSION_MAJOR << 16) | (QUIC_VERSION_MAJOR & 0xffff))
+
+#define ABS(a) ((a) >= 0 ? (a) : -(a))
+
+#ifdef DEBUG
+
+#define ASSERT(usr, x) \
+    if (!(x)) (usr)->error(usr, "%s: ASSERT %s failed\n", __FUNCTION__, #x);
+
+#else
+
+#define ASSERT(usr, x)
+
+#endif
+
+#define FALSE 0
+#define TRUE 1
+
+typedef uint8_t BYTE;
+
+/* maximum number of codes in family */
+#define MAXNUMCODES 8
+
+/* model evolution, warning: only 1,3 and 5 allowed */
+#define DEFevol 3
+#define MINevol 0
+#define MAXevol 5
+
+/* starting wait mask index */
+#define DEFwmistart 0
+#define MINwmistart 0
+
+/* codeword length limit */
+#define DEFmaxclen 26
+
+/* target wait mask index */
+#define DEFwmimax 6
+
+/* number of symbols to encode before increasing wait mask index */
+#define DEFwminext 2048
+#define MINwminext 1
+#define MAXwminext 100000000
+
+typedef struct QuicFamily {
+    unsigned int nGRcodewords[MAXNUMCODES];      /* indexed by code number, contains number of
+                                                    unmodofied GR codewords in the code */
+    unsigned int notGRcwlen[MAXNUMCODES];        /* indexed by code number, contains codeword
+                                                    length of the not-GR codeword */
+    unsigned int notGRprefixmask[MAXNUMCODES];   /* indexed by code number, contains mask to
+                                                    determine if the codeword is GR or not-GR */
+    unsigned int notGRsuffixlen[MAXNUMCODES];    /* indexed by code number, contains suffix
+                                                    length of the not-GR codeword */
+
+    /* array for translating distribution U to L for depths up to 8 bpp,
+    initialized by decorelateinit() */
+    BYTE xlatU2L[256];
+
+    /* array for translating distribution L to U for depths up to 8 bpp,
+       initialized by corelateinit() */
+    unsigned int xlatL2U[256];
+} QuicFamily;
+
+static QuicFamily family_8bpc;
+static QuicFamily family_5bpc;
+
+typedef unsigned COUNTER;   /* counter in the array of counters in bucket of the data model */
+
+typedef struct s_bucket {
+    COUNTER *pcounters;     /* pointer to array of counters */
+    unsigned int bestcode;  /* best code so far */
+} s_bucket;
+
+typedef struct Encoder Encoder;
+
+typedef struct CommonState {
+    Encoder *encoder;
+
+    unsigned int waitcnt;
+    unsigned int tabrand_seed;
+    unsigned int wm_trigger;
+    unsigned int wmidx;
+    unsigned int wmileft;
+
+#ifdef RLE_STAT
+    int melcstate; /* index to the state array */
+
+    int melclen;  /* contents of the state array location
+                     indexed by melcstate: the "expected"
+                     run length is 2^melclen, shorter runs are
+                     encoded by a 1 followed by the run length
+                     in binary representation, wit a fixed length
+                     of melclen bits */
+
+    unsigned long melcorder;  /* 2^ melclen */
+#endif
+} CommonState;
+
+
+#define MAX_CHANNELS 4
+
+typedef struct FamilyStat {
+    s_bucket **buckets_ptrs;
+    s_bucket *buckets_buf;
+    COUNTER *counters;
+} FamilyStat;
+
+typedef struct Channel {
+    Encoder *encoder;
+
+    int correlate_row_width;
+    BYTE *correlate_row;
+
+    s_bucket **_buckets_ptrs;
+
+    FamilyStat family_stat_8bpc;
+    FamilyStat family_stat_5bpc;
+
+    CommonState state;
+} Channel;
+
+struct Encoder {
+    QuicUsrContext *usr;
+    QuicImageType type;
+    unsigned int width;
+    unsigned int height;
+    unsigned int num_channels;
+
+    unsigned int n_buckets_8bpc;
+    unsigned int n_buckets_5bpc;
+
+    unsigned int io_available_bits;
+    uint32_t io_word;
+    uint32_t io_next_word;
+    uint32_t *io_now;
+    uint32_t *io_end;
+    uint32_t io_words_count;
+
+    int rows_completed;
+
+    Channel channels[MAX_CHANNELS];
+
+    CommonState rgb_state;
+};
+
+/* target wait mask index */
+static int wmimax = DEFwmimax;
+
+/* number of symbols to encode before increasing wait mask index */
+static int wminext = DEFwminext;
+
+/* model evolution mode */
+static int evol = DEFevol;
+
+/* bppmask[i] contains i ones as lsb-s */
+static const unsigned long int bppmask[33] = {
+    0x00000000, /* [0] */
+    0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
+    0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
+    0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
+    0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
+    0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
+    0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
+    0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff /* [32] */
+};
+
+static const unsigned int bitat[32] = {
+    0x00000001, 0x00000002, 0x00000004, 0x00000008,
+    0x00000010, 0x00000020, 0x00000040, 0x00000080,
+    0x00000100, 0x00000200, 0x00000400, 0x00000800,
+    0x00001000, 0x00002000, 0x00004000, 0x00008000,
+    0x00010000, 0x00020000, 0x00040000, 0x00080000,
+    0x00100000, 0x00200000, 0x00400000, 0x00800000,
+    0x01000000, 0x02000000, 0x04000000, 0x08000000,
+    0x10000000, 0x20000000, 0x40000000, 0x80000000 /* [31]*/
+};
+
+
+#define TABRAND_TABSIZE 256
+#define TABRAND_SEEDMASK 0x0ff
+
+static const unsigned int tabrand_chaos[TABRAND_TABSIZE] = {
+    0x02c57542, 0x35427717, 0x2f5a2153, 0x9244f155, 0x7bd26d07, 0x354c6052, 0x57329b28, 0x2993868e,
+    0x6cd8808c, 0x147b46e0, 0x99db66af, 0xe32b4cac, 0x1b671264, 0x9d433486, 0x62a4c192, 0x06089a4b,
+    0x9e3dce44, 0xdaabee13, 0x222425ea, 0xa46f331d, 0xcd589250, 0x8bb81d7f, 0xc8b736b9, 0x35948d33,
+    0xd7ac7fd0, 0x5fbe2803, 0x2cfbc105, 0x013dbc4e, 0x7a37820f, 0x39f88e9e, 0xedd58794, 0xc5076689,
+    0xfcada5a4, 0x64c2f46d, 0xb3ba3243, 0x8974b4f9, 0x5a05aebd, 0x20afcd00, 0x39e2b008, 0x88a18a45,
+    0x600bde29, 0xf3971ace, 0xf37b0a6b, 0x7041495b, 0x70b707ab, 0x06beffbb, 0x4206051f, 0xe13c4ee3,
+    0xc1a78327, 0x91aa067c, 0x8295f72a, 0x732917a6, 0x1d871b4d, 0x4048f136, 0xf1840e7e, 0x6a6048c1,
+    0x696cb71a, 0x7ff501c3, 0x0fc6310b, 0x57e0f83d, 0x8cc26e74, 0x11a525a2, 0x946934c7, 0x7cd888f0,
+    0x8f9d8604, 0x4f86e73b, 0x04520316, 0xdeeea20c, 0xf1def496, 0x67687288, 0xf540c5b2, 0x22401484,
+    0x3478658a, 0xc2385746, 0x01979c2c, 0x5dad73c8, 0x0321f58b, 0xf0fedbee, 0x92826ddf, 0x284bec73,
+    0x5b1a1975, 0x03df1e11, 0x20963e01, 0xa17cf12b, 0x740d776e, 0xa7a6bf3c, 0x01b5cce4, 0x1118aa76,
+    0xfc6fac0a, 0xce927e9b, 0x00bf2567, 0x806f216c, 0xbca69056, 0x795bd3e9, 0xc9dc4557, 0x8929b6c2,
+    0x789d52ec, 0x3f3fbf40, 0xb9197368, 0xa38c15b5, 0xc3b44fa8, 0xca8333b0, 0xb7e8d590, 0xbe807feb,
+    0xbf5f8360, 0xd99e2f5c, 0x372928e1, 0x7c757c4c, 0x0db5b154, 0xc01ede02, 0x1fc86e78, 0x1f3985be,
+    0xb4805c77, 0x00c880fa, 0x974c1b12, 0x35ab0214, 0xb2dc840d, 0x5b00ae37, 0xd313b026, 0xb260969d,
+    0x7f4c8879, 0x1734c4d3, 0x49068631, 0xb9f6a021, 0x6b863e6f, 0xcee5debf, 0x29f8c9fb, 0x53dd6880,
+    0x72b61223, 0x1f67a9fd, 0x0a0f6993, 0x13e59119, 0x11cca12e, 0xfe6b6766, 0x16b6effc, 0x97918fc4,
+    0xc2b8a563, 0x94f2f741, 0x0bfa8c9a, 0xd1537ae8, 0xc1da349c, 0x873c60ca, 0x95005b85, 0x9b5c080e,
+    0xbc8abbd9, 0xe1eab1d2, 0x6dac9070, 0x4ea9ebf1, 0xe0cf30d4, 0x1ef5bd7b, 0xd161043e, 0x5d2fa2e2,
+    0xff5d3cae, 0x86ed9f87, 0x2aa1daa1, 0xbd731a34, 0x9e8f4b22, 0xb1c2c67a, 0xc21758c9, 0xa182215d,
+    0xccb01948, 0x8d168df7, 0x04238cfe, 0x368c3dbc, 0x0aeadca5, 0xbad21c24, 0x0a71fee5, 0x9fc5d872,
+    0x54c152c6, 0xfc329483, 0x6783384a, 0xeddb3e1c, 0x65f90e30, 0x884ad098, 0xce81675a, 0x4b372f7d,
+    0x68bf9a39, 0x43445f1e, 0x40f8d8cb, 0x90d5acb6, 0x4cd07282, 0x349eeb06, 0x0c9d5332, 0x520b24ef,
+    0x80020447, 0x67976491, 0x2f931ca3, 0xfe9b0535, 0xfcd30220, 0x61a9e6cc, 0xa487d8d7, 0x3f7c5dd1,
+    0x7d0127c5, 0x48f51d15, 0x60dea871, 0xc9a91cb7, 0x58b53bb3, 0x9d5e0b2d, 0x624a78b4, 0x30dbee1b,
+    0x9bdf22e7, 0x1df5c299, 0x2d5643a7, 0xf4dd35ff, 0x03ca8fd6, 0x53b47ed8, 0x6f2c19aa, 0xfeb0c1f4,
+    0x49e54438, 0x2f2577e6, 0xbf876969, 0x72440ea9, 0xfa0bafb8, 0x74f5b3a0, 0x7dd357cd, 0x89ce1358,
+    0x6ef2cdda, 0x1e7767f3, 0xa6be9fdb, 0x4f5f88f8, 0xba994a3a, 0x08ca6b65, 0xe0893818, 0x9e00a16a,
+    0xf42bfc8f, 0x9972eedc, 0x749c8b51, 0x32c05f5e, 0xd706805f, 0x6bfbb7cf, 0xd9210a10, 0x31a1db97,
+    0x923a9559, 0x37a7a1f6, 0x059f8861, 0xca493e62, 0x65157e81, 0x8f6467dd, 0xab85ff9f, 0x9331aff2,
+    0x8616b9f5, 0xedbd5695, 0xee7e29b1, 0x313ac44f, 0xb903112f, 0x432ef649, 0xdc0a36c0, 0x61cf2bba,
+    0x81474925, 0xa8b6c7ad, 0xee5931de, 0xb2f8158d, 0x59fb7409, 0x2e3dfaed, 0x9af25a3f, 0xe1fed4d5,
+};
+
+static unsigned int stabrand()
+{
+    //ASSERT( !(TABRAND_SEEDMASK & TABRAND_TABSIZE));
+    //ASSERT( TABRAND_SEEDMASK + 1 == TABRAND_TABSIZE );
+
+    return TABRAND_SEEDMASK;
+}
+
+static unsigned int tabrand(unsigned int *tabrand_seed)
+{
+    return tabrand_chaos[++*tabrand_seed & TABRAND_SEEDMASK];
+}
+
+static const unsigned short besttrigtab[3][11] = { /* array of wm_trigger for waitmask and evol,
+                                                    used by set_wm_trigger() */
+    /* 1 */ { 550, 900, 800, 700, 500, 350, 300, 200, 180, 180, 160},
+    /* 3 */ { 110, 550, 900, 800, 550, 400, 350, 250, 140, 160, 140},
+    /* 5 */ { 100, 120, 550, 900, 700, 500, 400, 300, 220, 250, 160}
+};
+
+/* set wm_trigger knowing waitmask (param) and evol (glob)*/
+static void set_wm_trigger(CommonState *state)
+{
+    unsigned int wm = state->wmidx;
+    if (wm > 10) {
+        wm = 10;
+    }
+
+    ASSERT(state->encoder->usr, evol < 6);
+
+    state->wm_trigger = besttrigtab[evol / 2][wm];
+
+    ASSERT(state->encoder->usr, state->wm_trigger <= 2000);
+    ASSERT(state->encoder->usr, state->wm_trigger >= 1);
+}
+
+static int ceil_log_2(int val) /* ceil(log_2(val)) */
+{
+    int result;
+
+    //ASSERT(val>0);
+
+    if (val == 1) {
+        return 0;
+    }
+
+    result = 1;
+    val -= 1;
+    while (val >>= 1) {
+        result++;
+    }
+
+    return result;
+}
+
+/* number of leading zeroes in the byte, used by cntlzeroes(uint)*/
+static const BYTE lzeroes[256] = {
+    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* count leading zeroes */
+static unsigned int cnt_l_zeroes(const unsigned int bits)
+{
+    if (bits & 0xff800000) {
+        return lzeroes[bits >> 24];
+    } else if (bits & 0xffff8000) {
+        return 8 + lzeroes[(bits >> 16) & 0x000000ff];
+    } else if (bits & 0xffffff80) {
+        return 16 + lzeroes[(bits >> 8) & 0x000000ff];
+    } else {
+        return 24 + lzeroes[bits & 0x000000ff];
+    }
+}
+
+#define QUIC_FAMILY_8BPC
+#include "quic_family_tmpl.c"
+
+#ifdef QUIC_RGB
+#define QUIC_FAMILY_5BPC
+#include "quic_family_tmpl.c"
+#endif
+
+static void decorelate_init(QuicFamily *family, int bpc)
+{
+    const unsigned int pixelbitmask = bppmask[bpc];
+    const unsigned int pixelbitmaskshr = pixelbitmask >> 1;
+    unsigned int s;
+
+    //ASSERT(bpc <= 8);
+
+    for (s = 0; s <= pixelbitmask; s++) {
+        if (s <= pixelbitmaskshr) {
+            family->xlatU2L[s] = s << 1;
+        } else {
+            family->xlatU2L[s] = ((pixelbitmask - s) << 1) + 1;
+        }
+    }
+}
+
+static void corelate_init(QuicFamily *family, int bpc)
+{
+    const unsigned long int pixelbitmask = bppmask[bpc];
+    unsigned long int s;
+
+    //ASSERT(bpc <= 8);
+
+    for (s = 0; s <= pixelbitmask; s++) {
+        if (s & 0x01) {
+            family->xlatL2U[s] = pixelbitmask - (s >> 1);
+        } else {
+            family->xlatL2U[s] = (s >> 1);
+        }
+    }
+}
+
+static void family_init(QuicFamily *family, int bpc, int limit)
+{
+    int l;
+
+    for (l = 0; l < bpc; l++) { /* fill arrays indexed by code number */
+        int altprefixlen, altcodewords;
+
+        altprefixlen = limit - bpc;
+        if (altprefixlen > (int)(bppmask[bpc - l])) {
+            altprefixlen = bppmask[bpc - l];
+        }
+
+        altcodewords = bppmask[bpc] + 1 - (altprefixlen << l);
+
+        family->nGRcodewords[l] = (altprefixlen << l);
+        family->notGRcwlen[l] = altprefixlen + ceil_log_2(altcodewords);
+        family->notGRprefixmask[l] = bppmask[32 - altprefixlen]; /* needed for decoding only */
+        family->notGRsuffixlen[l] = ceil_log_2(altcodewords); /* needed for decoding only */
+    }
+
+    decorelate_init(family, bpc);
+    corelate_init(family, bpc);
+}
+
+static void more_io_words(Encoder *encoder)
+{
+    uint32_t *io_ptr;
+    int num_io_words = encoder->usr->more_space(encoder->usr, &io_ptr, encoder->rows_completed);
+    if (num_io_words <= 0) {
+        encoder->usr->error(encoder->usr, "%s: no more words\n", __FUNCTION__);
+    }
+    ASSERT(encoder->usr, io_ptr);
+    encoder->io_words_count += num_io_words;
+    encoder->io_now = io_ptr;
+    encoder->io_end = encoder->io_now + num_io_words;
+}
+
+static void __write_io_word(Encoder *encoder)
+{
+    more_io_words(encoder);
+    *(encoder->io_now++) = encoder->io_word;
+}
+
+static void (*__write_io_word_ptr)(Encoder *encoder) = __write_io_word;
+
+static INLINE void write_io_word(Encoder *encoder)
+{
+    if (encoder->io_now == encoder->io_end) {
+        __write_io_word_ptr(encoder); //disable inline optimizations
+        return;
+    }
+    *(encoder->io_now++) = encoder->io_word;
+}
+
+static INLINE void encode(Encoder *encoder, unsigned int word, unsigned int len)
+{
+    int delta;
+
+    ASSERT(encoder->usr, len > 0 && len < 32);
+    ASSERT(encoder->usr, !(word & ~bppmask[len]));
+    if ((delta = ((int)encoder->io_available_bits - len)) >= 0) {
+        encoder->io_available_bits = delta;
+        encoder->io_word |= word << encoder->io_available_bits;
+        return;
+    }
+    delta = -delta;
+    encoder->io_word |= word >> delta;
+    write_io_word(encoder);
+    encoder->io_available_bits = 32 - delta;
+    encoder->io_word = word << encoder->io_available_bits;
+
+    ASSERT(encoder->usr, encoder->io_available_bits < 32);
+    ASSERT(encoder->usr, (encoder->io_word & bppmask[encoder->io_available_bits]) == 0);
+}
+
+static INLINE void encode_32(Encoder *encoder, unsigned int word)
+{
+    encode(encoder, word >> 16, 16);
+    encode(encoder, word & 0x0000ffff, 16);
+}
+
+static INLINE void flush(Encoder *encoder)
+{
+    if (encoder->io_available_bits > 0 && encoder->io_available_bits != 32) {
+        encode(encoder, 0, encoder->io_available_bits);
+    }
+    encode_32(encoder, 0);
+    encode(encoder, 0, 1);
+}
+
+static void __read_io_word(Encoder *encoder)
+{
+    more_io_words(encoder);
+    encoder->io_next_word = *(encoder->io_now++);
+}
+
+static void (*__read_io_word_ptr)(Encoder *encoder) = __read_io_word;
+
+
+static INLINE void read_io_word(Encoder *encoder)
+{
+    if (encoder->io_now == encoder->io_end) {
+        __read_io_word_ptr(encoder); //disable inline optimizations
+        return;
+    }
+    ASSERT(encoder->usr, encoder->io_now < encoder->io_end);
+    encoder->io_next_word = *(encoder->io_now++);
+}
+
+static INLINE void decode_eatbits(Encoder *encoder, int len)
+{
+    int delta;
+
+    ASSERT(encoder->usr, len > 0 && len < 32);
+    encoder->io_word <<= len;
+
+    if ((delta = ((int)encoder->io_available_bits - len)) >= 0) {
+        encoder->io_available_bits = delta;
+        encoder->io_word |= encoder->io_next_word >> encoder->io_available_bits;
+        return;
+    }
+
+    delta = -delta;
+    encoder->io_word |= encoder->io_next_word << delta;
+    read_io_word(encoder);
+    encoder->io_available_bits = 32 - delta;
+    encoder->io_word |= (encoder->io_next_word >> encoder->io_available_bits);
+}
+
+static INLINE void decode_eat32bits(Encoder *encoder)
+{
+    decode_eatbits(encoder, 16);
+    decode_eatbits(encoder, 16);
+}
+
+#ifdef RLE
+
+#ifdef RLE_STAT
+
+static INLINE void encode_ones(Encoder *encoder, unsigned int n)
+{
+    unsigned int count;
+
+    for (count = n >> 5; count; count--) {
+        encode(encoder, ~0U, 32);
+    }
+
+    if ((n &= 0x1f)) {
+        encode(encoder, (1U << n) - 1, n);
+    }
+}
+
+#define MELCSTATES 32 /* number of melcode states */
+
+static int zeroLUT[256]; /* table to find out number of leading zeros */
+
+static int J[MELCSTATES] = {
+    0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7,
+    7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+/* creates the bit counting look-up table. */
+static void init_zeroLUT()
+{
+    int i, j, k, l;
+
+    j = k = 1;
+    l = 8;
+    for (i = 0; i < 256; ++i) {
+        zeroLUT[i] = l;
+        --k;
+        if (k == 0) {
+            k = j;
+            --l;
+            j *= 2;
+        }
+    }
+}
+
+static void encoder_init_rle(CommonState *state)
+{
+    state->melcstate = 0;
+    state->melclen = J[0];
+    state->melcorder = 1 << state->melclen;
+}
+
+#ifdef QUIC_RGB
+
+static void encode_run(Encoder *encoder, unsigned int runlen) //todo: try use end of line
+{
+    int hits = 0;
+
+    while (runlen >= encoder->rgb_state.melcorder) {
+        hits++;
+        runlen -= encoder->rgb_state.melcorder;
+        if (encoder->rgb_state.melcstate < MELCSTATES) {
+            encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate];
+            encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen);
+        }
+    }
+
+    /* send the required number of "hit" bits (one per occurrence
+       of a run of length melcorder). This number is never too big:
+       after 31 such "hit" bits, each "hit" would represent a run of 32K
+       pixels.
+    */
+    encode_ones(encoder, hits);
+
+    encode(encoder, runlen, encoder->rgb_state.melclen + 1);
+
+    /* adjust melcoder parameters */
+    if (encoder->rgb_state.melcstate) {
+        encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate];
+        encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen);
+    }
+}
+
+#endif
+
+static void encode_channel_run(Encoder *encoder, Channel *channel, unsigned int runlen)
+{
+    //todo: try use end of line
+    int hits = 0;
+
+    while (runlen >= channel->state.melcorder) {
+        hits++;
+        runlen -= channel->state.melcorder;
+        if (channel->state.melcstate < MELCSTATES) {
+            channel->state.melclen = J[++channel->state.melcstate];
+            channel->state.melcorder = (1L << channel->state.melclen);
+        }
+    }
+
+    /* send the required number of "hit" bits (one per occurrence
+       of a run of length melcorder). This number is never too big:
+       after 31 such "hit" bits, each "hit" would represent a run of 32K
+       pixels.
+    */
+    encode_ones(encoder, hits);
+
+    encode(encoder, runlen, channel->state.melclen + 1);
+
+    /* adjust melcoder parameters */
+    if (channel->state.melcstate) {
+        channel->state.melclen = J[--channel->state.melcstate];
+        channel->state.melcorder = (1L << channel->state.melclen);
+    }
+}
+
+/* decoding routine: reads bits from the input and returns a run length. */
+/* argument is the number of pixels left to end-of-line (bound on run length) */
+
+#ifdef QUIC_RGB
+static int decode_run(Encoder *encoder)
+{
+    int runlen = 0;
+
+    do {
+        register int temp, hits;
+        temp = zeroLUT[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the
+                                                                      input stream, up to 8 */
+        for (hits = 1; hits <= temp; hits++) {
+            runlen += encoder->rgb_state.melcorder;
+
+            if (encoder->rgb_state.melcstate < MELCSTATES) {
+                encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate];
+                encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen);
+            }
+        }
+        if (temp != 8) {
+            decode_eatbits(encoder, temp + 1);  /* consume the leading
+                                                            0 of the remainder encoding */
+            break;
+        }
+        decode_eatbits(encoder, 8);
+    } while (1);
+
+    /* read the length of the remainder */
+    if (encoder->rgb_state.melclen) {
+        runlen += encoder->io_word >> (32 - encoder->rgb_state.melclen);
+        decode_eatbits(encoder, encoder->rgb_state.melclen);
+    }
+
+    /* adjust melcoder parameters */
+    if (encoder->rgb_state.melcstate) {
+        encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate];
+        encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen);
+    }
+
+    return runlen;
+}
+
+#endif
+
+static int decode_channel_run(Encoder *encoder, Channel *channel)
+{
+    int runlen = 0;
+
+    do {
+        register int temp, hits;
+        temp = zeroLUT[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the
+                                                                      input stream, up to 8 */
+        for (hits = 1; hits <= temp; hits++) {
+            runlen += channel->state.melcorder;
+
+            if (channel->state.melcstate < MELCSTATES) {
+                channel->state.melclen = J[++channel->state.melcstate];
+                channel->state.melcorder = (1U << channel->state.melclen);
+            }
+        }
+        if (temp != 8) {
+            decode_eatbits(encoder, temp + 1);  /* consume the leading
+                                                            0 of the remainder encoding */
+            break;
+        }
+        decode_eatbits(encoder, 8);
+    } while (1);
+
+    /* read the length of the remainder */
+    if (channel->state.melclen) {
+        runlen += encoder->io_word >> (32 - channel->state.melclen);
+        decode_eatbits(encoder, channel->state.melclen);
+    }
+
+    /* adjust melcoder parameters */
+    if (channel->state.melcstate) {
+        channel->state.melclen = J[--channel->state.melcstate];
+        channel->state.melcorder = (1U << channel->state.melclen);
+    }
+
+    return runlen;
+}
+
+#else
+
+static INLINE int find_msb(int x)
+{
+    int r;
+
+    __asm__("bsrl %1,%0\n\t"
+            "jnz 1f\n\t"
+            "movl $-1,%0\n"
+            "1:" : "=r" (r) : "rm" (x));
+    return r + 1;
+}
+
+static INLINE void encode_run(Encoder *encoder, unsigned int len)
+{
+    int odd = len & 1U;
+    int msb;
+
+    len &= ~1U;
+
+    while ((msb = find_msb(len))) {
+        len &= ~(1 << (msb - 1));
+        ASSERT(encoder->usr, msb < 32);
+        encode(encoder, (1 << (msb)) - 1, msb);
+        encode(encoder, 0, 1);
+    }
+
+    if (odd) {
+        encode(encoder, 2, 2);
+    } else {
+        encode(encoder, 0, 1);
+    }
+}
+
+static INLINE unsigned int decode_run(Encoder *encoder)
+{
+    unsigned int len = 0;
+    int count;
+
+    do {
+        count = 0;
+        while (encoder->io_word & (1U << 31)) {
+            decode_eatbits(encoder, 1);
+            count++;
+            ASSERT(encoder->usr, count < 32);
+        }
+        decode_eatbits(encoder, 1);
+        len += (1U << count) >> 1;
+    } while (count > 1);
+
+    return len;
+}
+
+#endif
+#endif
+
+static INLINE void init_decode_io(Encoder *encoder)
+{
+    encoder->io_next_word = encoder->io_word = *(encoder->io_now++);
+    encoder->io_available_bits = 0;
+}
+
+#ifdef __GNUC__
+#define ATTR_PACKED __attribute__ ((__packed__))
+#else
+#define ATTR_PACKED
+#pragma pack(push)
+#pragma pack(1)
+#endif
+
+typedef struct ATTR_PACKED one_byte_pixel_t {
+    BYTE a;
+} one_byte_t;
+
+typedef struct ATTR_PACKED three_bytes_pixel_t {
+    BYTE a;
+    BYTE b;
+    BYTE c;
+} three_bytes_t;
+
+typedef struct ATTR_PACKED four_bytes_pixel_t {
+    BYTE a;
+    BYTE b;
+    BYTE c;
+    BYTE d;
+} four_bytes_t;
+
+typedef struct ATTR_PACKED rgb32_pixel_t {
+    BYTE b;
+    BYTE g;
+    BYTE r;
+    BYTE pad;
+} rgb32_pixel_t;
+
+typedef struct ATTR_PACKED rgb24_pixel_t {
+    BYTE b;
+    BYTE g;
+    BYTE r;
+} rgb24_pixel_t;
+
+typedef uint16_t rgb16_pixel_t;
+
+#ifndef __GNUC__
+#pragma pack(pop)
+#endif
+
+#undef ATTR_PACKED
+
+#define ONE_BYTE
+#include "quic_tmpl.c"
+
+#define FOUR_BYTE
+#include "quic_tmpl.c"
+
+#ifdef QUIC_RGB
+
+#define QUIC_RGB32
+#include "quic_rgb_tmpl.c"
+
+#define QUIC_RGB24
+#include "quic_rgb_tmpl.c"
+
+#define QUIC_RGB16
+#include "quic_rgb_tmpl.c"
+
+#define QUIC_RGB16_TO_32
+#include "quic_rgb_tmpl.c"
+
+#else
+
+#define THREE_BYTE
+#include "quic_tmpl.c"
+
+#endif
+
+static void fill_model_structures(Encoder *encoder, FamilyStat *family_stat,
+                                  unsigned int rep_first, unsigned int first_size,
+                                  unsigned int rep_next, unsigned int mul_size,
+                                  unsigned int levels, unsigned int ncounters,
+                                  unsigned int nbuckets, unsigned int n_buckets_ptrs)
+{
+    unsigned int
+    bsize,
+    bstart,
+    bend = 0,
+    repcntr,
+    bnumber;
+
+    COUNTER * free_counter = family_stat->counters;/* first free location in the array of
+                                                      counters */
+
+    bnumber = 0;
+
+    repcntr = rep_first + 1;    /* first bucket */
+    bsize = first_size;
+
+    do { /* others */
+        if (bnumber) {
+            bstart = bend + 1;
+        } else {
+            bstart = 0;
+        }
+
+        if (!--repcntr) {
+            repcntr = rep_next;
+            bsize *= mul_size;
+        }
+
+        bend = bstart + bsize - 1;
+        if (bend + bsize >= levels) {
+            bend = levels - 1;
+        }
+
+        family_stat->buckets_buf[bnumber].pcounters = free_counter;
+        free_counter += ncounters;
+
+        ASSERT(encoder->usr, bstart < n_buckets_ptrs);
+        {
+            unsigned int i;
+            ASSERT(encoder->usr, bend < n_buckets_ptrs);
+            for (i = bstart; i <= bend; i++) {
+                family_stat->buckets_ptrs[i] = family_stat->buckets_buf + bnumber;
+            }
+        }
+
+        bnumber++;
+    } while (bend < levels - 1);
+
+    ASSERT(encoder->usr, free_counter - family_stat->counters == nbuckets * ncounters);
+}
+
+static void find_model_params(Encoder *encoder,
+                              const int bpc,
+                              unsigned int *ncounters,
+                              unsigned int *levels,
+                              unsigned int *n_buckets_ptrs,
+                              unsigned int *repfirst,
+                              unsigned int *firstsize,
+                              unsigned int *repnext,
+                              unsigned int *mulsize,
+                              unsigned int *nbuckets)
+{
+    unsigned int bsize;              /* bucket size */
+    unsigned int bstart, bend = 0;   /* bucket start and end, range : 0 to levels-1*/
+    unsigned int repcntr;            /* helper */
+
+    ASSERT(encoder->usr, bpc <= 8 && bpc > 0);
+
+
+    *ncounters = 8;
+
+    *levels = 0x1 << bpc;
+
+    *n_buckets_ptrs = 0;  /* ==0 means: not set yet */
+
+    switch (evol) {   /* set repfirst firstsize repnext mulsize */
+    case 1: /* buckets contain following numbers of contexts: 1 1 1 2 2 4 4 8 8 ... */
+        *repfirst = 3;
+        *firstsize = 1;
+        *repnext = 2;
+        *mulsize = 2;
+        break;
+    case 3: /* 1 2 4 8 16 32 64 ... */
+        *repfirst = 1;
+        *firstsize = 1;
+        *repnext = 1;
+        *mulsize = 2;
+        break;
+    case 5:                     /* 1 4 16 64 256 1024 4096 16384 65536 */
+        *repfirst = 1;
+        *firstsize = 1;
+        *repnext = 1;
+        *mulsize = 4;
+        break;
+    case 0: /* obsolete */
+    case 2: /* obsolete */
+    case 4: /* obsolete */
+        encoder->usr->error(encoder->usr, "findmodelparams(): evol value obsolete!!!\n");
+    default:
+        encoder->usr->error(encoder->usr, "findmodelparams(): evol out of range!!!\n");
+    }
+
+    *nbuckets = 0;
+    repcntr = *repfirst + 1;    /* first bucket */
+    bsize = *firstsize;
+
+    do { /* other buckets */
+        if (nbuckets) {         /* bucket start */
+            bstart = bend + 1;
+        } else {
+            bstart = 0;
+        }
+
+        if (!--repcntr) {         /* bucket size */
+            repcntr = *repnext;
+            bsize *= *mulsize;
+        }
+
+        bend = bstart + bsize - 1;  /* bucket end */
+        if (bend + bsize >= *levels) {  /* if following bucked was bigger than current one */
+            bend = *levels - 1;     /* concatenate them */
+        }
+
+        if (!*n_buckets_ptrs) {           /* array size not set yet? */
+            *n_buckets_ptrs = *levels;
+ #if 0
+            if (bend == *levels - 1) {   /* this bucket is last - all in the first array */
+                *n_buckets_ptrs = *levels;
+            } else if (bsize >= 256) { /* this bucket is allowed to reside in the 2nd table */
+                b_lo_ptrs = bstart;
+                assert(bstart);     /* previous bucket exists */
+            }
+ #endif
+        }
+
+        (*nbuckets)++;
+    } while (bend < *levels - 1);
+}
+
+static int init_model_structures(Encoder *encoder, FamilyStat *family_stat,
+                                 unsigned int rep_first, unsigned int first_size,
+                                 unsigned int rep_next, unsigned int mul_size,
+                                 unsigned int levels, unsigned int ncounters,
+                                 unsigned int n_buckets_ptrs, unsigned int n_buckets)
+{
+    family_stat->buckets_ptrs = (s_bucket **)encoder->usr->malloc(encoder->usr,
+                                                                  n_buckets_ptrs *
+                                                                  sizeof(s_bucket *));
+    if (!family_stat->buckets_ptrs) {
+        return FALSE;
+    }
+
+    family_stat->counters = (COUNTER *)encoder->usr->malloc(encoder->usr,
+                                                            n_buckets * sizeof(COUNTER) *
+                                                            MAXNUMCODES);
+    if (!family_stat->counters) {
+        goto error_1;
+    }
+
+    family_stat->buckets_buf = (s_bucket *)encoder->usr->malloc(encoder->usr,
+                                                                n_buckets * sizeof(s_bucket));
+    if (!family_stat->buckets_buf) {
+        goto error_2;
+    }
+
+    fill_model_structures(encoder, family_stat, rep_first, first_size, rep_next, mul_size, levels,
+                          ncounters, n_buckets, n_buckets_ptrs);
+
+    return TRUE;
+
+error_2:
+    encoder->usr->free(encoder->usr, family_stat->counters);
+
+error_1:
+    encoder->usr->free(encoder->usr, family_stat->buckets_ptrs);
+
+    return FALSE;
+}
+
+static void free_family_stat(QuicUsrContext *usr, FamilyStat *family_stat)
+{
+    usr->free(usr, family_stat->buckets_ptrs);
+    usr->free(usr, family_stat->counters);
+    usr->free(usr, family_stat->buckets_buf);
+}
+
+static int init_channel(Encoder *encoder, Channel *channel)
+{
+    unsigned int ncounters;
+    unsigned int levels;
+    unsigned int rep_first;
+    unsigned int first_size;
+    unsigned int rep_next;
+    unsigned int mul_size;
+    unsigned int n_buckets;
+    unsigned int n_buckets_ptrs;
+
+    channel->encoder = encoder;
+    channel->state.encoder = encoder;
+    channel->correlate_row_width = 0;
+    channel->correlate_row = NULL;
+
+    find_model_params(encoder, 8, &ncounters, &levels, &n_buckets_ptrs, &rep_first,
+                      &first_size, &rep_next, &mul_size, &n_buckets);
+    encoder->n_buckets_8bpc = n_buckets;
+    if (!init_model_structures(encoder, &channel->family_stat_8bpc, rep_first, first_size,
+                               rep_next, mul_size, levels, ncounters, n_buckets_ptrs,
+                               n_buckets)) {
+        return FALSE;
+    }
+
+    find_model_params(encoder, 5, &ncounters, &levels, &n_buckets_ptrs, &rep_first,
+                      &first_size, &rep_next, &mul_size, &n_buckets);
+    encoder->n_buckets_5bpc = n_buckets;
+    if (!init_model_structures(encoder, &channel->family_stat_5bpc, rep_first, first_size,
+                               rep_next, mul_size, levels, ncounters, n_buckets_ptrs,
+                               n_buckets)) {
+        free_family_stat(encoder->usr, &channel->family_stat_8bpc);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void destroy_channel(Channel *channel)
+{
+    QuicUsrContext *usr = channel->encoder->usr;
+    if (channel->correlate_row) {
+        usr->free(usr, channel->correlate_row - 1);
+    }
+    free_family_stat(usr, &channel->family_stat_8bpc);
+    free_family_stat(usr, &channel->family_stat_5bpc);
+}
+
+static int init_encoder(Encoder *encoder, QuicUsrContext *usr)
+{
+    int i;
+
+    encoder->usr = usr;
+    encoder->rgb_state.encoder = encoder;
+
+    for (i = 0; i < MAX_CHANNELS; i++) {
+        if (!init_channel(encoder, &encoder->channels[i])) {
+            for (--i; i >= 0; i--) {
+                destroy_channel(&encoder->channels[i]);
+            }
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+static int encoder_reste(Encoder *encoder, uint32_t *io_ptr, uint32_t *io_ptr_end)
+{
+    ASSERT(encoder->usr, ((unsigned long)io_ptr % 4) == ((unsigned long)io_ptr_end % 4));
+    ASSERT(encoder->usr, io_ptr <= io_ptr_end);
+
+    encoder->rgb_state.waitcnt = 0;
+    encoder->rgb_state.tabrand_seed = stabrand();
+    encoder->rgb_state.wmidx = DEFwmistart;
+    encoder->rgb_state.wmileft = wminext;
+    set_wm_trigger(&encoder->rgb_state);
+
+#if defined(RLE) && defined(RLE_STAT)
+    encoder_init_rle(&encoder->rgb_state);
+#endif
+
+    encoder->io_words_count = io_ptr_end - io_ptr;
+    encoder->io_now = io_ptr;
+    encoder->io_end = io_ptr_end;
+    encoder->rows_completed = 0;
+
+    return TRUE;
+}
+
+static int encoder_reste_channels(Encoder *encoder, int channels, int width, int bpc)
+{
+    int i;
+
+    encoder->num_channels = channels;
+
+    for (i = 0; i < channels; i++) {
+        s_bucket *bucket;
+        s_bucket *end_bucket;
+
+        if (encoder->channels[i].correlate_row_width < width) {
+            encoder->channels[i].correlate_row_width = 0;
+            if (encoder->channels[i].correlate_row) {
+                encoder->usr->free(encoder->usr, encoder->channels[i].correlate_row - 1);
+            }
+            if (!(encoder->channels[i].correlate_row = (BYTE *)encoder->usr->malloc(encoder->usr,
+                                                                                    width + 1))) {
+                return FALSE;
+            }
+            encoder->channels[i].correlate_row++;
+            encoder->channels[i].correlate_row_width = width;
+        }
+
+        if (bpc == 8) {
+            MEMCLEAR(encoder->channels[i].family_stat_8bpc.counters,
+                     encoder->n_buckets_8bpc * sizeof(COUNTER) * MAXNUMCODES);
+            bucket = encoder->channels[i].family_stat_8bpc.buckets_buf;
+            end_bucket = bucket + encoder->n_buckets_8bpc;
+            for (; bucket < end_bucket; bucket++) {
+                bucket->bestcode = /*BPC*/ 8 - 1;
+            }
+            encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_8bpc.buckets_ptrs;
+        } else if (bpc == 5) {
+            MEMCLEAR(encoder->channels[i].family_stat_5bpc.counters,
+                     encoder->n_buckets_5bpc * sizeof(COUNTER) * MAXNUMCODES);
+            bucket = encoder->channels[i].family_stat_5bpc.buckets_buf;
+            end_bucket = bucket + encoder->n_buckets_5bpc;
+            for (; bucket < end_bucket; bucket++) {
+                bucket->bestcode = /*BPC*/ 5 - 1;
+            }
+            encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_5bpc.buckets_ptrs;
+        } else {
+            encoder->usr->warn(encoder->usr, "%s: bad bpc %d\n", __FUNCTION__, bpc);
+            return FALSE;
+        }
+
+        encoder->channels[i].state.waitcnt = 0;
+        encoder->channels[i].state.tabrand_seed = stabrand();
+        encoder->channels[i].state.wmidx = DEFwmistart;
+        encoder->channels[i].state.wmileft = wminext;
+        set_wm_trigger(&encoder->channels[i].state);
+
+#if defined(RLE) && defined(RLE_STAT)
+        encoder_init_rle(&encoder->channels[i].state);
+#endif
+    }
+    return TRUE;
+}
+
+static void quic_image_params(Encoder *encoder, QuicImageType type, int *channels, int *bpc)
+{
+    ASSERT(encoder->usr, channels && bpc);
+    switch (type) {
+    case QUIC_IMAGE_TYPE_GRAY:
+        *channels = 1;
+        *bpc = 8;
+        break;
+    case QUIC_IMAGE_TYPE_RGB16:
+        *channels = 3;
+        *bpc = 5;
+#ifndef QUIC_RGB
+        encoder->usr->error(encoder->usr, "not implemented\n");
+#endif
+        break;
+    case QUIC_IMAGE_TYPE_RGB24:
+        *channels = 3;
+        *bpc = 8;
+        break;
+    case QUIC_IMAGE_TYPE_RGB32:
+        *channels = 3;
+        *bpc = 8;
+        break;
+    case QUIC_IMAGE_TYPE_RGBA:
+        *channels = 4;
+        *bpc = 8;
+        break;
+    case QUIC_IMAGE_TYPE_INVALID:
+    default:
+        *channels = 0;
+        *bpc = 0;
+        encoder->usr->error(encoder->usr, "bad image type\n");
+    }
+}
+
+#define FILL_LINES() {                                                  \
+    if (line == lines_end) {                                            \
+        int n = encoder->usr->more_lines(encoder->usr, &line);          \
+        if (n <= 0) {                                                   \
+            encoder->usr->error(encoder->usr, "more lines failed\n");   \
+        }                                                               \
+        lines_end = line + n * stride;                                  \
+    }                                                                   \
+}
+
+#define NEXT_LINE() {       \
+    line += stride;         \
+    FILL_LINES();           \
+}
+
+#define QUIC_COMPRESS_RGB(bits)                                                                 \
+        encoder->channels[0].correlate_row[-1] = 0;                                             \
+        encoder->channels[1].correlate_row[-1] = 0;                                             \
+        encoder->channels[2].correlate_row[-1] = 0;                                             \
+        quic_rgb##bits##_compress_row0(encoder, (rgb##bits##_pixel_t *)(line), width);          \
+        encoder->rows_completed++;                                                              \
+        for (row = 1; row < height; row++) {                                                    \
+            prev = line;                                                                        \
+            NEXT_LINE();                                                                        \
+            encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];     \
+            encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];     \
+            encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];     \
+            quic_rgb##bits##_compress_row(encoder, (rgb##bits##_pixel_t *)prev,                 \
+                                          (rgb##bits##_pixel_t *)line, width);                  \
+            encoder->rows_completed++;                                                          \
+        }
+
+int quic_encode(QuicContext *quic, QuicImageType type, int width, int height,
+                uint8_t *line, unsigned int num_lines, int stride,
+                uint32_t *io_ptr, unsigned int num_io_words)
+{
+    Encoder *encoder = (Encoder *)quic;
+    uint32_t *io_ptr_end = io_ptr + num_io_words;
+    uint8_t *lines_end;
+    int row;
+    uint8_t *prev;
+    int channels;
+    int bpc;
+#ifndef QUIC_RGB
+    int i;
+#endif
+
+    ASSERT(encoder->usr, line);
+    lines_end = line + num_lines * stride;
+
+    quic_image_params(encoder, type, &channels, &bpc);
+
+    if (!encoder_reste(encoder, io_ptr, io_ptr_end) ||
+        !encoder_reste_channels(encoder, channels, width, bpc)) {
+        return QUIC_ERROR;
+    }
+
+    encoder->io_word = 0;
+    encoder->io_available_bits = 32;
+
+    encode_32(encoder, QUIC_MAGIC);
+    encode_32(encoder, QUIC_VERSION);
+    encode_32(encoder, type);
+    encode_32(encoder, width);
+    encode_32(encoder, height);
+
+    FILL_LINES();
+
+    switch (type) {
+#ifdef QUIC_RGB
+    case QUIC_IMAGE_TYPE_RGB32:
+        ASSERT(encoder->usr, ABS(stride) >= width * 4);
+        QUIC_COMPRESS_RGB(32);
+        break;
+    case QUIC_IMAGE_TYPE_RGB24:
+        ASSERT(encoder->usr, ABS(stride) >= width * 3);
+        QUIC_COMPRESS_RGB(24);
+        break;
+    case QUIC_IMAGE_TYPE_RGB16:
+        ASSERT(encoder->usr, ABS(stride) >= width * 2);
+        QUIC_COMPRESS_RGB(16);
+        break;
+    case QUIC_IMAGE_TYPE_RGBA:
+        ASSERT(encoder->usr, ABS(stride) >= width * 4);
+
+        encoder->channels[0].correlate_row[-1] = 0;
+        encoder->channels[1].correlate_row[-1] = 0;
+        encoder->channels[2].correlate_row[-1] = 0;
+        quic_rgb32_compress_row0(encoder, (rgb32_pixel_t *)(line), width);
+
+        encoder->channels[3].correlate_row[-1] = 0;
+        quic_four_compress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(line + 3), width);
+
+        encoder->rows_completed++;
+
+        for (row = 1; row < height; row++) {
+            prev = line;
+            NEXT_LINE();
+            encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
+            encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];
+            encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];
+            quic_rgb32_compress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)line, width);
+
+            encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0];
+            quic_four_compress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3),
+                                   (four_bytes_t *)(line + 3), width);
+            encoder->rows_completed++;
+        }
+        break;
+#else
+    case QUIC_IMAGE_TYPE_RGB24:
+        ASSERT(encoder->usr, ABS(stride) >= width * 3);
+        for (i = 0; i < 3; i++) {
+            encoder->channels[i].correlate_row[-1] = 0;
+            quic_three_compress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(line + i),
+                                     width);
+        }
+        encoder->rows_completed++;
+        for (row = 1; row < height; row++) {
+            prev = line;
+            NEXT_LINE();
+            for (i = 0; i < 3; i++) {
+                encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
+                quic_three_compress_row(encoder, &encoder->channels[i], (three_bytes_t *)(prev + i),
+                                        (three_bytes_t *)(line + i), width);
+            }
+            encoder->rows_completed++;
+        }
+        break;
+    case QUIC_IMAGE_TYPE_RGB32:
+    case QUIC_IMAGE_TYPE_RGBA:
+        ASSERT(encoder->usr, ABS(stride) >= width * 4);
+        for (i = 0; i < channels; i++) {
+            encoder->channels[i].correlate_row[-1] = 0;
+            quic_four_compress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(line + i),
+                                    width);
+        }
+        encoder->rows_completed++;
+        for (row = 1; row < height; row++) {
+            prev = line;
+            NEXT_LINE();
+            for (i = 0; i < channels; i++) {
+                encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
+                quic_four_compress_row(encoder, &encoder->channels[i], (four_bytes_t *)(prev + i),
+                                       (four_bytes_t *)(line + i), width);
+            }
+            encoder->rows_completed++;
+        }
+        break;
+#endif
+    case QUIC_IMAGE_TYPE_GRAY:
+        ASSERT(encoder->usr, ABS(stride) >= width);
+        encoder->channels[0].correlate_row[-1] = 0;
+        quic_one_compress_row0(encoder, &encoder->channels[0], (one_byte_t *)line, width);
+        encoder->rows_completed++;
+        for (row = 1; row < height; row++) {
+            prev = line;
+            NEXT_LINE();
+            encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
+            quic_one_compress_row(encoder, &encoder->channels[0], (one_byte_t *)prev,
+                                  (one_byte_t *)line, width);
+            encoder->rows_completed++;
+        }
+        break;
+    case QUIC_IMAGE_TYPE_INVALID:
+    default:
+        encoder->usr->error(encoder->usr, "bad image type\n");
+    }
+
+    flush(encoder);
+    encoder->io_words_count -= (encoder->io_end - encoder->io_now);
+
+    return encoder->io_words_count;
+}
+
+int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words,
+                      QuicImageType *out_type, int *out_width, int *out_height)
+{
+    Encoder *encoder = (Encoder *)quic;
+    uint32_t *io_ptr_end = io_ptr + num_io_words;
+    QuicImageType type;
+    int width;
+    int height;
+    uint32_t magic;
+    uint32_t version;
+    int channels;
+    int bpc;
+
+    if (!encoder_reste(encoder, io_ptr, io_ptr_end)) {
+        return QUIC_ERROR;
+    }
+
+    init_decode_io(encoder);
+
+    magic = encoder->io_word;
+    decode_eat32bits(encoder);
+    if (magic != QUIC_MAGIC) {
+        encoder->usr->warn(encoder->usr, "bad magic\n");
+        return QUIC_ERROR;
+    }
+
+    version = encoder->io_word;
+    decode_eat32bits(encoder);
+    if (version != QUIC_VERSION) {
+        encoder->usr->warn(encoder->usr, "bad version\n");
+        return QUIC_ERROR;
+    }
+
+    type = (QuicImageType)encoder->io_word;
+    decode_eat32bits(encoder);
+
+    width = encoder->io_word;
+    decode_eat32bits(encoder);
+
+    height = encoder->io_word;
+    decode_eat32bits(encoder);
+
+    quic_image_params(encoder, type, &channels, &bpc);
+
+    if (!encoder_reste_channels(encoder, channels, width, bpc)) {
+        return QUIC_ERROR;
+    }
+
+    *out_width = encoder->width = width;
+    *out_height = encoder->height = height;
+    *out_type = encoder->type = type;
+    return QUIC_OK;
+}
+
+#ifndef QUIC_RGB
+static void clear_row(four_bytes_t *row, int width)
+{
+    four_bytes_t *end;
+    for (end = row + width; row < end; row++) {
+        row->a = 0;
+    }
+}
+
+#endif
+
+#ifdef QUIC_RGB
+
+static void uncompress_rgba(Encoder *encoder, uint8_t *buf, int stride)
+{
+    unsigned int row;
+    uint8_t *prev;
+
+    encoder->channels[0].correlate_row[-1] = 0;
+    encoder->channels[1].correlate_row[-1] = 0;
+    encoder->channels[2].correlate_row[-1] = 0;
+    quic_rgb32_uncompress_row0(encoder, (rgb32_pixel_t *)buf, encoder->width);
+
+    encoder->channels[3].correlate_row[-1] = 0;
+    quic_four_uncompress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(buf + 3),
+                              encoder->width);
+
+    encoder->rows_completed++;
+    for (row = 1; row < encoder->height; row++) {
+        prev = buf;
+        buf += stride;
+
+        encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
+        encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];
+        encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];
+        quic_rgb32_uncompress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)buf,
+                                  encoder->width);
+
+        encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0];
+        quic_four_uncompress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3),
+                                 (four_bytes_t *)(buf + 3), encoder->width);
+
+        encoder->rows_completed++;
+    }
+}
+
+#endif
+
+static void uncompress_gray(Encoder *encoder, uint8_t *buf, int stride)
+{
+    unsigned int row;
+    uint8_t *prev;
+
+    encoder->channels[0].correlate_row[-1] = 0;
+    quic_one_uncompress_row0(encoder, &encoder->channels[0], (one_byte_t *)buf, encoder->width);
+    encoder->rows_completed++;
+    for (row = 1; row < encoder->height; row++) {
+        prev = buf;
+        buf += stride;
+        encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
+        quic_one_uncompress_row(encoder, &encoder->channels[0], (one_byte_t *)prev,
+                                (one_byte_t *)buf, encoder->width);
+        encoder->rows_completed++;
+    }
+}
+
+#define QUIC_UNCOMPRESS_RGB(prefix, type)                                                       \
+        encoder->channels[0].correlate_row[-1] = 0;                                             \
+        encoder->channels[1].correlate_row[-1] = 0;                                             \
+        encoder->channels[2].correlate_row[-1] = 0;                                             \
+        quic_rgb##prefix##_uncompress_row0(encoder, (type *)buf, encoder->width);  \
+        encoder->rows_completed++;                                                              \
+        for (row = 1; row < encoder->height; row++) {                                           \
+            prev = buf;                                                                         \
+            buf += stride;                                                                      \
+            encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];     \
+            encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];     \
+            encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];     \
+            quic_rgb##prefix##_uncompress_row(encoder, (type *)prev, (type *)buf,               \
+                                              encoder->width);                                  \
+            encoder->rows_completed++;                                                          \
+        }
+        
+int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride)
+{
+    Encoder *encoder = (Encoder *)quic;
+    unsigned int row;
+    uint8_t *prev;
+#ifndef QUIC_RGB
+    int i;
+#endif
+
+    ASSERT(encoder->usr, buf);
+
+    switch (encoder->type) {
+#ifdef QUIC_RGB
+    case QUIC_IMAGE_TYPE_RGB32:
+    case QUIC_IMAGE_TYPE_RGB24:
+        if (type == QUIC_IMAGE_TYPE_RGB32) {
+            ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4);
+            QUIC_UNCOMPRESS_RGB(32, rgb32_pixel_t);
+            break;
+        } else if (type == QUIC_IMAGE_TYPE_RGB24) {
+            ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 3);
+            QUIC_UNCOMPRESS_RGB(24, rgb24_pixel_t);
+            break;
+        }
+        encoder->usr->warn(encoder->usr, "unsupported output format\n");
+        return QUIC_ERROR;
+    case QUIC_IMAGE_TYPE_RGB16:
+        if (type == QUIC_IMAGE_TYPE_RGB16) {
+            ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 2);
+            QUIC_UNCOMPRESS_RGB(16, rgb16_pixel_t);
+        } else if (type == QUIC_IMAGE_TYPE_RGB32) {
+            ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4);
+            QUIC_UNCOMPRESS_RGB(16_to_32, rgb32_pixel_t);
+        } else {
+            encoder->usr->warn(encoder->usr, "unsupported output format\n");
+            return QUIC_ERROR;
+        }
+
+        break;
+    case QUIC_IMAGE_TYPE_RGBA:
+
+        if (type != QUIC_IMAGE_TYPE_RGBA) {
+            encoder->usr->warn(encoder->usr, "unsupported output format\n");
+            return QUIC_ERROR;
+        }
+        ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4);
+        uncompress_rgba(encoder, buf, stride);
+        break;
+#else
+    case QUIC_IMAGE_TYPE_RGB24:
+        ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 3);
+        for (i = 0; i < 3; i++) {
+            encoder->channels[i].correlate_row[-1] = 0;
+            quic_three_uncompress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(buf + i),
+                                       encoder->width);
+        }
+        encoder->rows_completed++;
+        for (row = 1; row < encoder->height; row++) {
+            prev = buf;
+            buf += stride;
+            for (i = 0; i < 3; i++) {
+                encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
+                quic_three_uncompress_row(encoder, &encoder->channels[i],
+                                          (three_bytes_t *)(prev + i),
+                                          (three_bytes_t *)(buf + i),
+                                          encoder->width);
+            }
+            encoder->rows_completed++;
+        }
+        break;
+    case QUIC_IMAGE_TYPE_RGB32:
+        ASSERT(encoder->usr, ABS(stride) >= encoder->width * 4);
+        for (i = 0; i < 3; i++) {
+            encoder->channels[i].correlate_row[-1] = 0;
+            quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i),
+                                      encoder->width);
+        }
+        clear_row((four_bytes_t *)(buf + 3), encoder->width);
+        encoder->rows_completed++;
+        for (row = 1; row < encoder->height; row++) {
+            prev = buf;
+            buf += stride;
+            for (i = 0; i < 3; i++) {
+                encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
+                quic_four_uncompress_row(encoder, &encoder->channels[i],
+                                         (four_bytes_t *)(prev + i),
+                                         (four_bytes_t *)(buf + i),
+                                         encoder->width);
+            }
+            clear_row((four_bytes_t *)(buf + 3), encoder->width);
+            encoder->rows_completed++;
+        }
+        break;
+    case QUIC_IMAGE_TYPE_RGBA:
+        ASSERT(encoder->usr, ABS(stride) >= encoder->width * 4);
+        for (i = 0; i < 4; i++) {
+            encoder->channels[i].correlate_row[-1] = 0;
+            quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i),
+                                      encoder->width);
+        }
+        encoder->rows_completed++;
+        for (row = 1; row < encoder->height; row++) {
+            prev = buf;
+            buf += stride;
+            for (i = 0; i < 4; i++) {
+                encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
+                quic_four_uncompress_row(encoder, &encoder->channels[i],
+                                         (four_bytes_t *)(prev + i),
+                                         (four_bytes_t *)(buf + i),
+                                         encoder->width);
+            }
+            encoder->rows_completed++;
+        }
+        break;
+#endif
+    case QUIC_IMAGE_TYPE_GRAY:
+
+        if (type != QUIC_IMAGE_TYPE_GRAY) {
+            encoder->usr->warn(encoder->usr, "unsupported output format\n");
+            return QUIC_ERROR;
+        }
+        ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width);
+        uncompress_gray(encoder, buf, stride);
+        break;
+    case QUIC_IMAGE_TYPE_INVALID:
+    default:
+        encoder->usr->error(encoder->usr, "bad image type\n");
+    }
+    return QUIC_OK;
+}
+
+static int need_init = TRUE;
+
+QuicContext *quic_create(QuicUsrContext *usr)
+{
+    Encoder *encoder;
+
+    if (!usr || need_init || !usr->error || !usr->warn || !usr->info || !usr->malloc ||
+        !usr->free || !usr->more_space || !usr->more_lines) {
+        return NULL;
+    }
+
+    if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) {
+        return NULL;
+    }
+
+    if (!init_encoder(encoder, usr)) {
+        usr->free(usr, encoder);
+        return NULL;
+    }
+    return (QuicContext *)encoder;
+}
+
+void quic_destroy(QuicContext *quic)
+{
+    Encoder *encoder = (Encoder *)quic;
+    int i;
+
+    if (!quic) {
+        return;
+    }
+
+    for (i = 0; i < MAX_CHANNELS; i++) {
+        destroy_channel(&encoder->channels[i]);
+    }
+    encoder->usr->free(encoder->usr, encoder);
+}
+
+void quic_init()
+{
+    if (!need_init) {
+        return;
+    }
+    need_init = FALSE;
+
+    family_init(&family_8bpc, 8, DEFmaxclen);
+    family_init(&family_5bpc, 5, DEFmaxclen);
+#if defined(RLE) && defined(RLE_STAT)
+    init_zeroLUT();
+#endif
+}
+
diff --git a/display/quic.h b/display/quic.h
new file mode 100644
index 0000000..8824db7
--- /dev/null
+++ b/display/quic.h
@@ -0,0 +1,64 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __QUIC_H
+#define __QUIC_H
+
+#include "quic_config.h"
+
+typedef enum {
+    QUIC_IMAGE_TYPE_INVALID,
+    QUIC_IMAGE_TYPE_GRAY,
+    QUIC_IMAGE_TYPE_RGB16,
+    QUIC_IMAGE_TYPE_RGB24,
+    QUIC_IMAGE_TYPE_RGB32,
+    QUIC_IMAGE_TYPE_RGBA
+} QuicImageType;
+
+#define QUIC_ERROR -1
+#define QUIC_OK 0
+
+typedef void *QuicContext;
+
+typedef struct QuicUsrContext QuicUsrContext;
+struct QuicUsrContext {
+    void (*error)(QuicUsrContext *usr, const char *fmt, ...);
+    void (*warn)(QuicUsrContext *usr, const char *fmt, ...);
+    void (*info)(QuicUsrContext *usr, const char *fmt, ...);
+    void *(*malloc)(QuicUsrContext *usr, int size);
+    void (*free)(QuicUsrContext *usr, void *ptr);
+    int (*more_space)(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed);
+    int (*more_lines)(QuicUsrContext *usr, uint8_t **lines); // on return the last line of previous
+                                                             // lines bunch must stil be valid
+};
+
+int quic_encode(QuicContext *quic, QuicImageType type, int width, int height,
+                uint8_t *lines, unsigned int num_lines, int stride,
+                uint32_t *io_ptr, unsigned int num_io_words);
+
+int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words,
+                      QuicImageType *type, int *width, int *height);
+int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride);
+
+
+QuicContext *quic_create(QuicUsrContext *usr);
+void quic_destroy(QuicContext *quic);
+
+void quic_init();
+
+#endif
+
diff --git a/display/quic_config.h b/display/quic_config.h
new file mode 100644
index 0000000..c9eb8fa
--- /dev/null
+++ b/display/quic_config.h
@@ -0,0 +1,50 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __QUIC_CONFIG_H
+#define __QUIC_CONFIG_H
+
+#include <spice/types.h>
+
+#ifdef __GNUC__
+
+#include <string.h>
+
+#define INLINE inline
+
+#define MEMCLEAR(ptr, size) memset(ptr, 0, size)
+
+#else
+
+#ifdef QXLDD
+#include <windef.h>
+#include "os_dep.h"
+#define INLINE _inline
+#define MEMCLEAR(ptr, size) RtlZeroMemory(ptr, size)
+#else
+#include <stddef.h>
+#include <string.h>
+
+#define INLINE inline
+#define MEMCLEAR(ptr, size) memset(ptr, 0, size)
+#endif
+
+
+#endif
+
+#endif
+
diff --git a/display/quic_family_tmpl.c b/display/quic_family_tmpl.c
new file mode 100644
index 0000000..58ae693
--- /dev/null
+++ b/display/quic_family_tmpl.c
@@ -0,0 +1,114 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef QUIC_FAMILY_8BPC
+#undef QUIC_FAMILY_8BPC
+#define FNAME(name) name##_8bpc
+#define VNAME(name) name##_8bpc
+#define BPC 8
+#endif
+
+
+#ifdef QUIC_FAMILY_5BPC
+#undef QUIC_FAMILY_5BPC
+#define FNAME(name) name##_5bpc
+#define VNAME(name) name##_5bpc
+#define BPC 5
+#endif
+
+
+static unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l)
+{
+    if (n < VNAME(family).nGRcodewords[l]) {
+        return (n >> l) + 1 + l;
+    } else {
+        return VNAME(family).notGRcwlen[l];
+    }
+}
+
+static void FNAME(golomb_coding)(const BYTE n, const unsigned int l, unsigned int * const codeword,
+                                 unsigned int * const codewordlen)
+{
+    if (n < VNAME(family).nGRcodewords[l]) {
+        (*codeword) = bitat[l] | (n & bppmask[l]);
+        (*codewordlen) = (n >> l) + l + 1;
+    } else {
+        (*codeword) = n - VNAME(family).nGRcodewords[l];
+        (*codewordlen) = VNAME(family).notGRcwlen[l];
+    }
+}
+
+unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned int bits,
+                                    unsigned int * const codewordlen)
+{
+    if (bits > VNAME(family).notGRprefixmask[l]) { /*GR*/
+        const unsigned int zeroprefix = cnt_l_zeroes(bits);       /* leading zeroes in codeword */
+        const unsigned int cwlen = zeroprefix + 1 + l;            /* codeword length */
+        (*codewordlen) = cwlen;
+        return (zeroprefix << l) | ((bits >> (32 - cwlen)) & bppmask[l]);
+    } else { /* not-GR */
+        const unsigned int cwlen = VNAME(family).notGRcwlen[l];
+        (*codewordlen) = cwlen;
+        return VNAME(family).nGRcodewords[l] + ((bits) >> (32 - cwlen) &
+                                                bppmask[VNAME(family).notGRsuffixlen[l]]);
+    }
+}
+
+/* update the bucket using just encoded curval */
+static void FNAME(update_model)(CommonState *state, s_bucket * const bucket,
+                                const BYTE curval, unsigned int bpp)
+{
+    COUNTER * const pcounters = bucket->pcounters;
+    unsigned int i;
+    unsigned int bestcode;
+    unsigned int bestcodelen;
+    //unsigned int bpp = encoder->bpp;
+
+    /* update counters, find minimum */
+
+    bestcode = bpp - 1;
+    bestcodelen = (pcounters[bestcode] += FNAME(golomb_code_len)(curval, bestcode));
+
+    for (i = bpp - 2; i < bpp; i--) { /* NOTE: expression i<bpp for signed int i would be: i>=0 */
+        const unsigned int ithcodelen = (pcounters[i] += FNAME(golomb_code_len)(curval, i));
+
+        if (ithcodelen < bestcodelen) {
+            bestcode = i;
+            bestcodelen = ithcodelen;
+        }
+    }
+
+    bucket->bestcode = bestcode; /* store the found minimum */
+
+    if (bestcodelen > state->wm_trigger) { /* halving counters? */
+        for (i = 0; i < bpp; i++) {
+            pcounters[i] >>= 1;
+        }
+    }
+}
+
+static s_bucket *FNAME(find_bucket)(Channel *channel, const unsigned int val)
+{
+    ASSERT(channel->encoder->usr, val < (0x1U << BPC));
+
+    return channel->_buckets_ptrs[val];
+}
+
+#undef FNAME
+#undef VNAME
+#undef BPC
+
diff --git a/display/quic_rgb_tmpl.c b/display/quic_rgb_tmpl.c
new file mode 100644
index 0000000..2007df6
--- /dev/null
+++ b/display/quic_rgb_tmpl.c
@@ -0,0 +1,762 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef QUIC_RGB32
+#undef QUIC_RGB32
+#define PIXEL rgb32_pixel_t
+#define FNAME(name) quic_rgb32_##name
+#define golomb_coding golomb_coding_8bpc
+#define golomb_decoding golomb_decoding_8bpc
+#define update_model update_model_8bpc
+#define find_bucket find_bucket_8bpc
+#define family family_8bpc
+#define BPC 8
+#define BPC_MASK 0xffU
+#define COMPRESS_IMP
+#define SET_r(pix, val) ((pix)->r = val)
+#define GET_r(pix) ((pix)->r)
+#define SET_g(pix, val) ((pix)->g = val)
+#define GET_g(pix) ((pix)->g)
+#define SET_b(pix, val) ((pix)->b = val)
+#define GET_b(pix) ((pix)->b)
+#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0)
+#endif
+
+#ifdef QUIC_RGB24
+#undef QUIC_RGB24
+#define PIXEL rgb24_pixel_t
+#define FNAME(name) quic_rgb24_##name
+#define golomb_coding golomb_coding_8bpc
+#define golomb_decoding golomb_decoding_8bpc
+#define update_model update_model_8bpc
+#define find_bucket find_bucket_8bpc
+#define family family_8bpc
+#define BPC 8
+#define BPC_MASK 0xffU
+#define COMPRESS_IMP
+#define SET_r(pix, val) ((pix)->r = val)
+#define GET_r(pix) ((pix)->r)
+#define SET_g(pix, val) ((pix)->g = val)
+#define GET_g(pix) ((pix)->g)
+#define SET_b(pix, val) ((pix)->b = val)
+#define GET_b(pix) ((pix)->b)
+#define UNCOMPRESS_PIX_START(pix)
+#endif
+
+#ifdef QUIC_RGB16
+#undef QUIC_RGB16
+#define PIXEL rgb16_pixel_t
+#define FNAME(name) quic_rgb16_##name
+#define golomb_coding golomb_coding_5bpc
+#define golomb_decoding golomb_decoding_5bpc
+#define update_model update_model_5bpc
+#define find_bucket find_bucket_5bpc
+#define family family_5bpc
+#define BPC 5
+#define BPC_MASK 0x1fU
+#define COMPRESS_IMP
+#define SET_r(pix, val) (*(pix) = (*(pix) & ~(0x1f << 10)) | ((val) << 10))
+#define GET_r(pix) ((*(pix) >> 10) & 0x1f)
+#define SET_g(pix, val) (*(pix) = (*(pix) & ~(0x1f << 5)) | ((val) << 5))
+#define GET_g(pix) ((*(pix) >> 5) & 0x1f)
+#define SET_b(pix, val) (*(pix) = (*(pix) & ~0x1f) | (val))
+#define GET_b(pix) (*(pix) & 0x1f)
+#define UNCOMPRESS_PIX_START(pix) (*(pix) = 0)
+#endif
+
+#ifdef QUIC_RGB16_TO_32
+#undef QUIC_RGB16_TO_32
+#define PIXEL rgb32_pixel_t
+#define FNAME(name) quic_rgb16_to_32_##name
+#define golomb_coding golomb_coding_5bpc
+#define golomb_decoding golomb_decoding_5bpc
+#define update_model update_model_5bpc
+#define find_bucket find_bucket_5bpc
+#define family family_5bpc
+#define BPC 5
+#define BPC_MASK 0x1fU
+
+#define SET_r(pix, val) ((pix)->r = ((val) << 3) | (((val) & 0x1f) >> 2))
+#define GET_r(pix) ((pix)->r >> 3)
+#define SET_g(pix, val) ((pix)->g = ((val) << 3) | (((val) & 0x1f) >> 2))
+#define GET_g(pix) ((pix)->g >> 3)
+#define SET_b(pix, val) ((pix)->b = ((val) << 3) | (((val) & 0x1f) >> 2))
+#define GET_b(pix) ((pix)->b >> 3)
+#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0)
+#endif
+
+#define SAME_PIXEL(p1, p2)                                 \
+    (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) &&   \
+     GET_b(p1) == GET_b(p2))
+
+
+#define _PIXEL_A(channel, curr) ((unsigned int)GET_##channel((curr) - 1))
+#define _PIXEL_B(channel, prev) ((unsigned int)GET_##channel(prev))
+#define _PIXEL_C(channel, prev) ((unsigned int)GET_##channel((prev) - 1))
+
+/*  a  */
+
+#define DECORELATE_0(channel, curr, bpc_mask)\
+    family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)_PIXEL_A(channel, curr)) & bpc_mask]
+
+#define CORELATE_0(channel, curr, correlate, bpc_mask)\
+    ((family.xlatL2U[correlate] + _PIXEL_A(channel, curr)) & bpc_mask)
+
+#ifdef PRED_1
+
+/*  (a+b)/2  */
+#define DECORELATE(channel, prev, curr, bpc_mask, r)                                            \
+    r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)((_PIXEL_A(channel, curr) +   \
+                        _PIXEL_B(channel, prev)) >> 1)) & bpc_mask]
+
+#define CORELATE(channel, prev, curr, correlate, bpc_mask, r)                                   \
+    SET_##channel(r, ((family.xlatL2U[correlate] +                                              \
+          (int)((_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev)) >> 1)) & bpc_mask))
+#endif
+
+#ifdef PRED_2
+
+/*  .75a+.75b-.5c  */
+#define DECORELATE(channel, prev, curr, bpc_mask, r) {                          \
+    int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) -   \
+                        (int)(_PIXEL_C(channel, prev) << 1)) >> 2;              \
+    if (p < 0) {                                                                \
+        p = 0;                                                                  \
+    } else if ((unsigned)p > bpc_mask) {                                        \
+        p = bpc_mask;                                                           \
+    }                                                                           \
+    r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - p) & bpc_mask];    \
+}
+
+#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) {                         \
+    const int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) -     \
+                        (int)(_PIXEL_C(channel, prev) << 1) ) >> 2;                     \
+    const unsigned int s = family.xlatL2U[correlate];                                   \
+    if (!(p & ~bpc_mask)) {                                                             \
+        SET_##channel(r, (s + (unsigned)p) & bpc_mask);                                 \
+    } else if (p < 0) {                                                                 \
+        SET_##channel(r, s);                                                            \
+    } else {                                                                            \
+        SET_##channel(r, (s + bpc_mask) & bpc_mask);                                    \
+    }                                                                                   \
+}
+
+#endif
+
+
+#define COMPRESS_ONE_ROW0_0(channel)                                                \
+    correlate_row_##channel[0] = family.xlatU2L[GET_##channel(cur_row)];            \
+    golomb_coding(correlate_row_##channel[0], find_bucket(channel_##channel,        \
+                  correlate_row_##channel[-1])->bestcode,                           \
+                  &codeword, &codewordlen);                                         \
+    encode(encoder, codeword, codewordlen);
+
+#define COMPRESS_ONE_ROW0(channel, index)                                               \
+    correlate_row_##channel[index] = DECORELATE_0(channel, &cur_row[index], bpc_mask);  \
+    golomb_coding(correlate_row_##channel[index], find_bucket(channel_##channel,        \
+                  correlate_row_##channel[index -1])->bestcode,                         \
+                  &codeword, &codewordlen);                                             \
+    encode(encoder, codeword, codewordlen);
+
+#define UPDATE_MODEL(index)                                                                 \
+    update_model(&encoder->rgb_state, find_bucket(channel_r, correlate_row_r[index - 1]),   \
+                correlate_row_r[index], bpc);                                               \
+    update_model(&encoder->rgb_state, find_bucket(channel_g, correlate_row_g[index - 1]),   \
+                correlate_row_g[index], bpc);                                               \
+    update_model(&encoder->rgb_state, find_bucket(channel_b, correlate_row_b[index - 1]),   \
+                correlate_row_b[index], bpc);
+
+
+#ifdef RLE_PRED_1
+#define RLE_PRED_1_IMP                                                                          \
+if (SAME_PIXEL(&cur_row[i - 1], &prev_row[i])) {                                                \
+    if (run_index != i && SAME_PIXEL(&prev_row[i - 1], &prev_row[i]) &&                         \
+                                i + 1 < end && SAME_PIXEL(&prev_row[i], &prev_row[i + 1])) {    \
+        goto do_run;                                                                            \
+    }                                                                                           \
+}
+#else
+#define RLE_PRED_1_IMP
+#endif
+
+#ifdef RLE_PRED_2
+#define RLE_PRED_2_IMP                                                              \
+if (SAME_PIXEL(&prev_row[i - 1], &prev_row[i])) {                                   \
+    if (run_index != i && i > 2 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2])) {  \
+        goto do_run;                                                                \
+    }                                                                               \
+}
+#else
+#define RLE_PRED_2_IMP
+#endif
+
+#ifdef RLE_PRED_3
+#define RLE_PRED_3_IMP                                                              \
+if (i > 1 &&  SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2]) && i != run_index) {     \
+    goto do_run;                                                                    \
+}
+#else
+#define RLE_PRED_3_IMP
+#endif
+
+#ifdef COMPRESS_IMP
+
+static void FNAME(compress_row0_seg)(Encoder *encoder, int i,
+                                     const PIXEL * const cur_row,
+                                     const int end,
+                                     const unsigned int waitmask,
+                                     const unsigned int bpc,
+                                     const unsigned int bpc_mask)
+{
+    Channel * const channel_r = encoder->channels;
+    Channel * const channel_g = channel_r + 1;
+    Channel * const channel_b = channel_g + 1;
+
+    BYTE * const correlate_row_r = channel_r->correlate_row;
+    BYTE * const correlate_row_g = channel_g->correlate_row;
+    BYTE * const correlate_row_b = channel_b->correlate_row;
+    int stopidx;
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (!i) {
+        unsigned int codeword, codewordlen;
+
+        COMPRESS_ONE_ROW0_0(r);
+        COMPRESS_ONE_ROW0_0(g);
+        COMPRESS_ONE_ROW0_0(b);
+
+        if (encoder->rgb_state.waitcnt) {
+            encoder->rgb_state.waitcnt--;
+        } else {
+            encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+            UPDATE_MODEL(0);
+        }
+        stopidx = ++i + encoder->rgb_state.waitcnt;
+    } else {
+        stopidx = i + encoder->rgb_state.waitcnt;
+    }
+
+    while (stopidx < end) {
+        for (; i <= stopidx; i++) {
+            unsigned int codeword, codewordlen;
+            COMPRESS_ONE_ROW0(r, i);
+            COMPRESS_ONE_ROW0(g, i);
+            COMPRESS_ONE_ROW0(b, i);
+        }
+
+        UPDATE_MODEL(stopidx);
+        stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+    }
+
+    for (; i < end; i++) {
+        unsigned int codeword, codewordlen;
+
+        COMPRESS_ONE_ROW0(r, i);
+        COMPRESS_ONE_ROW0(g, i);
+        COMPRESS_ONE_ROW0(b, i);
+    }
+    encoder->rgb_state.waitcnt = stopidx - end;
+}
+
+static void FNAME(compress_row0)(Encoder *encoder, const PIXEL *cur_row,
+                                 unsigned int width)
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    int pos = 0;
+
+    while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
+        if (encoder->rgb_state.wmileft) {
+            FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + encoder->rgb_state.wmileft,
+                                     bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
+            width -= encoder->rgb_state.wmileft;
+            pos += encoder->rgb_state.wmileft;
+        }
+
+        encoder->rgb_state.wmidx++;
+        set_wm_trigger(&encoder->rgb_state);
+        encoder->rgb_state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + width,
+                                 bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
+        if (wmimax > (int)encoder->rgb_state.wmidx) {
+            encoder->rgb_state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
+    ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+#define COMPRESS_ONE_0(channel) \
+    correlate_row_##channel[0] = family.xlatU2L[(unsigned)((int)GET_##channel(cur_row) -    \
+                                                (int)GET_##channel(prev_row) ) & bpc_mask]; \
+    golomb_coding(correlate_row_##channel[0],                                               \
+                  find_bucket(channel_##channel, correlate_row_##channel[-1])->bestcode,    \
+                  &codeword, &codewordlen);                                                 \
+    encode(encoder, codeword, codewordlen);
+
+#define COMPRESS_ONE(channel, index)                                                            \
+    DECORELATE(channel, &prev_row[index], &cur_row[index],bpc_mask,                             \
+               correlate_row_##channel[index]);                                                 \
+    golomb_coding(correlate_row_##channel[index],                                               \
+                 find_bucket(channel_##channel, correlate_row_##channel[index - 1])->bestcode,  \
+                 &codeword, &codewordlen);                                                      \
+    encode(encoder, codeword, codewordlen);
+
+static void FNAME(compress_row_seg)(Encoder *encoder, int i,
+                                    const PIXEL * const prev_row,
+                                    const PIXEL * const cur_row,
+                                    const int end,
+                                    const unsigned int waitmask,
+                                    const unsigned int bpc,
+                                    const unsigned int bpc_mask)
+{
+    Channel * const channel_r = encoder->channels;
+    Channel * const channel_g = channel_r + 1;
+    Channel * const channel_b = channel_g + 1;
+
+    BYTE * const correlate_row_r = channel_r->correlate_row;
+    BYTE * const correlate_row_g = channel_g->correlate_row;
+    BYTE * const correlate_row_b = channel_b->correlate_row;
+    int stopidx;
+#ifdef RLE
+    int run_index = 0;
+    int run_size;
+#endif
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (!i) {
+        unsigned int codeword, codewordlen;
+
+        COMPRESS_ONE_0(r);
+        COMPRESS_ONE_0(g);
+        COMPRESS_ONE_0(b);
+
+        if (encoder->rgb_state.waitcnt) {
+            encoder->rgb_state.waitcnt--;
+        } else {
+            encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+            UPDATE_MODEL(0);
+        }
+        stopidx = ++i + encoder->rgb_state.waitcnt;
+    } else {
+        stopidx = i + encoder->rgb_state.waitcnt;
+    }
+    for (;;) {
+        while (stopidx < end) {
+            for (; i <= stopidx; i++) {
+                unsigned int codeword, codewordlen;
+#ifdef RLE
+                RLE_PRED_1_IMP;
+                RLE_PRED_2_IMP;
+                RLE_PRED_3_IMP;
+#endif
+                COMPRESS_ONE(r, i);
+                COMPRESS_ONE(g, i);
+                COMPRESS_ONE(b, i);
+            }
+
+            UPDATE_MODEL(stopidx);
+            stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+        }
+
+        for (; i < end; i++) {
+            unsigned int codeword, codewordlen;
+#ifdef RLE
+            RLE_PRED_1_IMP;
+            RLE_PRED_2_IMP;
+            RLE_PRED_3_IMP;
+#endif
+            COMPRESS_ONE(r, i);
+            COMPRESS_ONE(g, i);
+            COMPRESS_ONE(b, i);
+        }
+        encoder->rgb_state.waitcnt = stopidx - end;
+
+        return;
+
+#ifdef RLE
+do_run:
+        run_index = i;
+        encoder->rgb_state.waitcnt = stopidx - i;
+        run_size = 0;
+
+        while (SAME_PIXEL(&cur_row[i], &cur_row[i - 1])) {
+            run_size++;
+            if (++i == end) {
+                encode_run(encoder, run_size);
+                return;
+            }
+        }
+        encode_run(encoder, run_size);
+        stopidx = i + encoder->rgb_state.waitcnt;
+#endif
+    }
+}
+
+static void FNAME(compress_row)(Encoder *encoder,
+                                const PIXEL * const prev_row,
+                                const PIXEL * const cur_row,
+                                unsigned int width)
+
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    unsigned int pos = 0;
+
+    while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
+        if (encoder->rgb_state.wmileft) {
+            FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row,
+                                    pos + encoder->rgb_state.wmileft,
+                                    bppmask[encoder->rgb_state.wmidx],
+                                    bpc, bpc_mask);
+            width -= encoder->rgb_state.wmileft;
+            pos += encoder->rgb_state.wmileft;
+        }
+
+        encoder->rgb_state.wmidx++;
+        set_wm_trigger(&encoder->rgb_state);
+        encoder->rgb_state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row, pos + width,
+                                bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
+        if (wmimax > (int)encoder->rgb_state.wmidx) {
+            encoder->rgb_state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
+    ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+#endif
+
+#define UNCOMPRESS_ONE_ROW0_0(channel)                                                          \
+    correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel,           \
+                                                       correlate_row_##channel[-1])->bestcode,  \
+                                                       encoder->io_word, &codewordlen);         \
+    SET_##channel(&cur_row[0], (BYTE)family.xlatL2U[correlate_row_##channel[0]]);               \
+    decode_eatbits(encoder, codewordlen);
+
+#define UNCOMPRESS_ONE_ROW0(channel)                                                              \
+    correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel,             \
+                                                       correlate_row_##channel[i - 1])->bestcode, \
+                                                       encoder->io_word,                          \
+                                                       &codewordlen);                             \
+    SET_##channel(&cur_row[i], CORELATE_0(channel, &cur_row[i], correlate_row_##channel[i],       \
+                  bpc_mask));                                                                     \
+    decode_eatbits(encoder, codewordlen);
+
+static void FNAME(uncompress_row0_seg)(Encoder *encoder, int i,
+                                       PIXEL * const cur_row,
+                                       const int end,
+                                       const unsigned int waitmask,
+                                       const unsigned int bpc,
+                                       const unsigned int bpc_mask)
+{
+    Channel * const channel_r = encoder->channels;
+    Channel * const channel_g = channel_r + 1;
+    Channel * const channel_b = channel_g + 1;
+
+    BYTE * const correlate_row_r = channel_r->correlate_row;
+    BYTE * const correlate_row_g = channel_g->correlate_row;
+    BYTE * const correlate_row_b = channel_b->correlate_row;
+    int stopidx;
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (!i) {
+        unsigned int codewordlen;
+
+        UNCOMPRESS_PIX_START(&cur_row[i]);
+        UNCOMPRESS_ONE_ROW0_0(r);
+        UNCOMPRESS_ONE_ROW0_0(g);
+        UNCOMPRESS_ONE_ROW0_0(b);
+
+        if (encoder->rgb_state.waitcnt) {
+            --encoder->rgb_state.waitcnt;
+        } else {
+            encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+            UPDATE_MODEL(0);
+        }
+        stopidx = ++i + encoder->rgb_state.waitcnt;
+    } else {
+        stopidx = i + encoder->rgb_state.waitcnt;
+    }
+
+    while (stopidx < end) {
+        for (; i <= stopidx; i++) {
+            unsigned int codewordlen;
+
+            UNCOMPRESS_PIX_START(&cur_row[i]);
+            UNCOMPRESS_ONE_ROW0(r);
+            UNCOMPRESS_ONE_ROW0(g);
+            UNCOMPRESS_ONE_ROW0(b);
+        }
+        UPDATE_MODEL(stopidx);
+        stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+    }
+
+    for (; i < end; i++) {
+        unsigned int codewordlen;
+
+        UNCOMPRESS_PIX_START(&cur_row[i]);
+        UNCOMPRESS_ONE_ROW0(r);
+        UNCOMPRESS_ONE_ROW0(g);
+        UNCOMPRESS_ONE_ROW0(b);
+    }
+    encoder->rgb_state.waitcnt = stopidx - end;
+}
+
+static void FNAME(uncompress_row0)(Encoder *encoder,
+                                   PIXEL * const cur_row,
+                                   unsigned int width)
+
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    unsigned int pos = 0;
+
+    while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
+        if (encoder->rgb_state.wmileft) {
+            FNAME(uncompress_row0_seg)(encoder, pos, cur_row,
+                                       pos + encoder->rgb_state.wmileft,
+                                       bppmask[encoder->rgb_state.wmidx],
+                                       bpc, bpc_mask);
+            pos += encoder->rgb_state.wmileft;
+            width -= encoder->rgb_state.wmileft;
+        }
+
+        encoder->rgb_state.wmidx++;
+        set_wm_trigger(&encoder->rgb_state);
+        encoder->rgb_state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(uncompress_row0_seg)(encoder, pos, cur_row, pos + width,
+                                   bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
+        if (wmimax > (int)encoder->rgb_state.wmidx) {
+            encoder->rgb_state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
+    ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+#define UNCOMPRESS_ONE_0(channel) \
+    correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel,           \
+                                                       correlate_row_##channel[-1])->bestcode,  \
+                                                       encoder->io_word, &codewordlen);         \
+    SET_##channel(&cur_row[0], (family.xlatL2U[correlate_row_##channel[0]] +                    \
+                          GET_##channel(prev_row)) & bpc_mask);                                 \
+    decode_eatbits(encoder, codewordlen);
+
+#define UNCOMPRESS_ONE(channel)                                                                   \
+    correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel,             \
+                                                       correlate_row_##channel[i - 1])->bestcode, \
+                                                       encoder->io_word,                          \
+                                                       &codewordlen);                             \
+    CORELATE(channel, &prev_row[i], &cur_row[i], correlate_row_##channel[i], bpc_mask,            \
+             &cur_row[i]);                                                                        \
+    decode_eatbits(encoder, codewordlen);
+
+static void FNAME(uncompress_row_seg)(Encoder *encoder,
+                                      const PIXEL * const prev_row,
+                                      PIXEL * const cur_row,
+                                      int i,
+                                      const int end,
+                                      const unsigned int bpc,
+                                      const unsigned int bpc_mask)
+{
+    Channel * const channel_r = encoder->channels;
+    Channel * const channel_g = channel_r + 1;
+    Channel * const channel_b = channel_g + 1;
+
+    BYTE * const correlate_row_r = channel_r->correlate_row;
+    BYTE * const correlate_row_g = channel_g->correlate_row;
+    BYTE * const correlate_row_b = channel_b->correlate_row;
+    const unsigned int waitmask = bppmask[encoder->rgb_state.wmidx];
+    int stopidx;
+#ifdef RLE
+    int run_index = 0;
+    int run_end;
+#endif
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (!i) {
+        unsigned int codewordlen;
+
+        UNCOMPRESS_PIX_START(&cur_row[i]);
+        UNCOMPRESS_ONE_0(r);
+        UNCOMPRESS_ONE_0(g);
+        UNCOMPRESS_ONE_0(b);
+
+        if (encoder->rgb_state.waitcnt) {
+            --encoder->rgb_state.waitcnt;
+        } else {
+            encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+            UPDATE_MODEL(0);
+        }
+        stopidx = ++i + encoder->rgb_state.waitcnt;
+    } else {
+        stopidx = i + encoder->rgb_state.waitcnt;
+    }
+    for (;;) {
+        while (stopidx < end) {
+            for (; i <= stopidx; i++) {
+                unsigned int codewordlen;
+#ifdef RLE
+                RLE_PRED_1_IMP;
+                RLE_PRED_2_IMP;
+                RLE_PRED_3_IMP;
+#endif
+                UNCOMPRESS_PIX_START(&cur_row[i]);
+                UNCOMPRESS_ONE(r);
+                UNCOMPRESS_ONE(g);
+                UNCOMPRESS_ONE(b);
+            }
+
+            UPDATE_MODEL(stopidx);
+
+            stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
+        }
+
+        for (; i < end; i++) {
+            unsigned int codewordlen;
+#ifdef RLE
+            RLE_PRED_1_IMP;
+            RLE_PRED_2_IMP;
+            RLE_PRED_3_IMP;
+#endif
+            UNCOMPRESS_PIX_START(&cur_row[i]);
+            UNCOMPRESS_ONE(r);
+            UNCOMPRESS_ONE(g);
+            UNCOMPRESS_ONE(b);
+        }
+
+        encoder->rgb_state.waitcnt = stopidx - end;
+
+        return;
+
+#ifdef RLE
+do_run:
+        encoder->rgb_state.waitcnt = stopidx - i;
+        run_index = i;
+        run_end = i + decode_run(encoder);
+
+        for (; i < run_end; i++) {
+            UNCOMPRESS_PIX_START(&cur_row[i]);
+            SET_r(&cur_row[i], GET_r(&cur_row[i - 1]));
+            SET_g(&cur_row[i], GET_g(&cur_row[i - 1]));
+            SET_b(&cur_row[i], GET_b(&cur_row[i - 1]));
+        }
+
+        if (i == end) {
+            return;
+        }
+
+        stopidx = i + encoder->rgb_state.waitcnt;
+#endif
+    }
+}
+
+static void FNAME(uncompress_row)(Encoder *encoder,
+                                  const PIXEL * const prev_row,
+                                  PIXEL * const cur_row,
+                                  unsigned int width)
+
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    unsigned int pos = 0;
+
+    while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
+        if (encoder->rgb_state.wmileft) {
+            FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos,
+                                      pos + encoder->rgb_state.wmileft, bpc, bpc_mask);
+            pos += encoder->rgb_state.wmileft;
+            width -= encoder->rgb_state.wmileft;
+        }
+
+        encoder->rgb_state.wmidx++;
+        set_wm_trigger(&encoder->rgb_state);
+        encoder->rgb_state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos,
+                                  pos + width, bpc, bpc_mask);
+        if (wmimax > (int)encoder->rgb_state.wmidx) {
+            encoder->rgb_state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
+    ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+#undef PIXEL
+#undef FNAME
+#undef _PIXEL_A
+#undef _PIXEL_B
+#undef _PIXEL_C
+#undef SAME_PIXEL
+#undef RLE_PRED_1_IMP
+#undef RLE_PRED_2_IMP
+#undef RLE_PRED_3_IMP
+#undef UPDATE_MODEL
+#undef DECORELATE_0
+#undef DECORELATE
+#undef COMPRESS_ONE_ROW0_0
+#undef COMPRESS_ONE_ROW0
+#undef COMPRESS_ONE_0
+#undef COMPRESS_ONE
+#undef CORELATE_0
+#undef CORELATE
+#undef UNCOMPRESS_ONE_ROW0_0
+#undef UNCOMPRESS_ONE_ROW0
+#undef UNCOMPRESS_ONE_0
+#undef UNCOMPRESS_ONE
+#undef golomb_coding
+#undef golomb_decoding
+#undef update_model
+#undef find_bucket
+#undef family
+#undef BPC
+#undef BPC_MASK
+#undef COMPRESS_IMP
+#undef SET_r
+#undef GET_r
+#undef SET_g
+#undef GET_g
+#undef SET_b
+#undef GET_b
+#undef UNCOMPRESS_PIX_START
+
diff --git a/display/quic_tmpl.c b/display/quic_tmpl.c
new file mode 100644
index 0000000..5a0a8e5
--- /dev/null
+++ b/display/quic_tmpl.c
@@ -0,0 +1,632 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef ONE_BYTE
+#undef ONE_BYTE
+#define FNAME(name) quic_one_##name
+#define PIXEL one_byte_t
+#endif
+
+#ifdef THREE_BYTE
+#undef THREE_BYTE
+#define FNAME(name) quic_three_##name
+#define PIXEL three_bytes_t
+#endif
+
+#ifdef FOUR_BYTE
+#undef FOUR_BYTE
+#define FNAME(name) quic_four_##name
+#define PIXEL four_bytes_t
+#endif
+
+#define golomb_coding golomb_coding_8bpc
+#define golomb_decoding golomb_decoding_8bpc
+#define update_model update_model_8bpc
+#define find_bucket find_bucket_8bpc
+#define family family_8bpc
+
+#define BPC 8
+#define BPC_MASK 0xffU
+
+#define _PIXEL_A ((unsigned int)curr[-1].a)
+#define _PIXEL_B ((unsigned int)prev[0].a)
+#define _PIXEL_C ((unsigned int)prev[-1].a)
+
+#ifdef RLE_PRED_1
+#define RLE_PRED_1_IMP                                                              \
+if (cur_row[i - 1].a == prev_row[i].a) {                                            \
+    if (run_index != i && prev_row[i - 1].a == prev_row[i].a &&                     \
+                        i + 1 < end && prev_row[i].a == prev_row[i + 1].a) {        \
+        goto do_run;                                                                \
+    }                                                                               \
+}
+#else
+#define RLE_PRED_1_IMP
+#endif
+
+#ifdef RLE_PRED_2
+#define RLE_PRED_2_IMP                                                     \
+if (prev_row[i - 1].a == prev_row[i].a) {                                  \
+    if (run_index != i && i > 2 && cur_row[i - 1].a == cur_row[i - 2].a) { \
+        goto do_run;                                                       \
+    }                                                                      \
+}
+#else
+#define RLE_PRED_2_IMP
+#endif
+
+#ifdef RLE_PRED_3
+#define RLE_PRED_3_IMP                                                  \
+if (i > 1 && cur_row[i - 1].a == cur_row[i - 2].a && i != run_index) {  \
+    goto do_run;                                                        \
+}
+#else
+#define RLE_PRED_3_IMP
+#endif
+
+/*  a  */
+static INLINE BYTE FNAME(decorelate_0)(const PIXEL * const curr, const unsigned int bpc_mask)
+{
+    return family.xlatU2L[(unsigned)((int)curr[0].a - (int)_PIXEL_A) & bpc_mask];
+}
+
+static INLINE void FNAME(corelate_0)(PIXEL *curr, const BYTE corelate,
+                                     const unsigned int bpc_mask)
+{
+    curr->a = (family.xlatL2U[corelate] + _PIXEL_A) & bpc_mask;
+}
+
+#ifdef PRED_1
+
+/*  (a+b)/2  */
+static INLINE BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr,
+                                     const unsigned int bpc_mask)
+{
+    return family.xlatU2L[(unsigned)((int)curr->a - (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask];
+}
+
+
+static INLINE void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate,
+                                   const unsigned int bpc_mask)
+{
+    curr->a = (family.xlatL2U[corelate] + (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask;
+}
+
+#endif
+
+#ifdef PRED_2
+
+/*  .75a+.75b-.5c  */
+static INLINE BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr,
+                                     const unsigned int bpc_mask)
+{
+    int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2;
+
+    if (p < 0) {
+        p = 0;
+    } else if ((unsigned)p > bpc_mask) {
+        p = bpc_mask;
+    }
+
+    {
+        return family.xlatU2L[(unsigned)((int)curr->a - p) & bpc_mask];
+    }
+}
+
+static INLINE void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate,
+                                   const unsigned int bpc_mask)
+{
+    const int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2;
+    const unsigned int s = family.xlatL2U[corelate];
+
+    if (!(p & ~bpc_mask)) {
+        curr->a = (s + (unsigned)p) & bpc_mask;
+    } else if (p < 0) {
+        curr->a = s;
+    } else {
+        curr->a = (s + bpc_mask) & bpc_mask;
+    }
+}
+
+#endif
+
+static void FNAME(compress_row0_seg)(Encoder *encoder, Channel *channel, int i,
+                                     const PIXEL * const cur_row,
+                                     const int end,
+                                     const unsigned int waitmask,
+                                     const unsigned int bpc,
+                                     const unsigned int bpc_mask)
+{
+    BYTE * const decorelate_drow = channel->correlate_row;
+    int stopidx;
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (i == 0) {
+        unsigned int codeword, codewordlen;
+
+        decorelate_drow[0] = family.xlatU2L[cur_row->a];
+        golomb_coding(decorelate_drow[0], find_bucket(channel, decorelate_drow[-1])->bestcode,
+                      &codeword, &codewordlen);
+        encode(encoder, codeword, codewordlen);
+
+        if (channel->state.waitcnt) {
+            channel->state.waitcnt--;
+        } else {
+            channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
+            update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]),
+                         decorelate_drow[i], bpc);
+        }
+        stopidx = ++i + channel->state.waitcnt;
+    } else {
+        stopidx = i + channel->state.waitcnt;
+    }
+
+    while (stopidx < end) {
+        for (; i <= stopidx; i++) {
+            unsigned int codeword, codewordlen;
+            decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask);
+            golomb_coding(decorelate_drow[i],
+                          find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword,
+                          &codewordlen);
+            encode(encoder, codeword, codewordlen);
+        }
+
+        update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]),
+                     decorelate_drow[stopidx], bpc);
+        stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
+    }
+
+    for (; i < end; i++) {
+        unsigned int codeword, codewordlen;
+        decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask);
+        golomb_coding(decorelate_drow[i], find_bucket(channel, decorelate_drow[i - 1])->bestcode,
+                      &codeword, &codewordlen);
+        encode(encoder, codeword, codewordlen);
+    }
+    channel->state.waitcnt = stopidx - end;
+}
+
+static void FNAME(compress_row0)(Encoder *encoder, Channel *channel, const PIXEL *cur_row,
+                                 unsigned int width)
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    int pos = 0;
+
+    while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
+        if (channel->state.wmileft) {
+            FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + channel->state.wmileft,
+                                     bppmask[channel->state.wmidx], bpc, bpc_mask);
+            width -= channel->state.wmileft;
+            pos += channel->state.wmileft;
+        }
+
+        channel->state.wmidx++;
+        set_wm_trigger(&channel->state);
+        channel->state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + width,
+                                 bppmask[channel->state.wmidx], bpc, bpc_mask);
+        if (wmimax > (int)channel->state.wmidx) {
+            channel->state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
+    ASSERT(encoder->usr, channel->state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+static void FNAME(compress_row_seg)(Encoder *encoder, Channel *channel, int i,
+                                    const PIXEL * const prev_row,
+                                    const PIXEL * const cur_row,
+                                    const int end,
+                                    const unsigned int waitmask,
+                                    const unsigned int bpc,
+                                    const unsigned int bpc_mask)
+{
+    BYTE * const decorelate_drow = channel->correlate_row;
+    int stopidx;
+#ifdef RLE
+    int run_index = 0;
+    int run_size;
+#endif
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (!i) {
+        unsigned int codeword, codewordlen;
+
+        decorelate_drow[0] = family.xlatU2L[(unsigned)((int)cur_row->a -
+                                                       (int)prev_row->a) & bpc_mask];
+
+        golomb_coding(decorelate_drow[0],
+                      find_bucket(channel, decorelate_drow[-1])->bestcode,
+                      &codeword,
+                      &codewordlen);
+        encode(encoder, codeword, codewordlen);
+
+        if (channel->state.waitcnt) {
+            channel->state.waitcnt--;
+        } else {
+            channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
+            update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]),
+                         decorelate_drow[0], bpc);
+        }
+        stopidx = ++i + channel->state.waitcnt;
+    } else {
+        stopidx = i + channel->state.waitcnt;
+    }
+    for (;;) {
+        while (stopidx < end) {
+            for (; i <= stopidx; i++) {
+                unsigned int codeword, codewordlen;
+#ifdef RLE
+                RLE_PRED_1_IMP;
+                RLE_PRED_2_IMP;
+                RLE_PRED_3_IMP;
+#endif
+                decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask);
+                golomb_coding(decorelate_drow[i],
+                              find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword,
+                              &codewordlen);
+                encode(encoder, codeword, codewordlen);
+            }
+
+            update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]),
+                         decorelate_drow[stopidx], bpc);
+            stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
+        }
+
+        for (; i < end; i++) {
+            unsigned int codeword, codewordlen;
+#ifdef RLE
+            RLE_PRED_1_IMP;
+            RLE_PRED_2_IMP;
+            RLE_PRED_3_IMP;
+#endif
+            decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask);
+            golomb_coding(decorelate_drow[i], find_bucket(channel,
+                                                          decorelate_drow[i - 1])->bestcode,
+                          &codeword, &codewordlen);
+            encode(encoder, codeword, codewordlen);
+        }
+        channel->state.waitcnt = stopidx - end;
+
+        return;
+
+#ifdef RLE
+do_run:
+        run_index = i;
+        channel->state.waitcnt = stopidx - i;
+        run_size = 0;
+
+        while (cur_row[i].a == cur_row[i - 1].a) {
+            run_size++;
+            if (++i == end) {
+#ifdef RLE_STAT
+                encode_channel_run(encoder, channel, run_size);
+#else
+                encode_run(encoder, run_size);
+#endif
+                return;
+            }
+        }
+#ifdef RLE_STAT
+        encode_channel_run(encoder, channel, run_size);
+#else
+        encode_run(encoder, run_size);
+#endif
+        stopidx = i + channel->state.waitcnt;
+#endif
+    }
+}
+
+static void FNAME(compress_row)(Encoder *encoder, Channel *channel,
+                                const PIXEL * const prev_row,
+                                const PIXEL * const cur_row,
+                                unsigned int width)
+
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    unsigned int pos = 0;
+
+    while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
+        if (channel->state.wmileft) {
+            FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row,
+                                    pos + channel->state.wmileft, bppmask[channel->state.wmidx],
+                                    bpc, bpc_mask);
+            width -= channel->state.wmileft;
+            pos += channel->state.wmileft;
+        }
+
+        channel->state.wmidx++;
+        set_wm_trigger(&channel->state);
+        channel->state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row, pos + width,
+                                bppmask[channel->state.wmidx], bpc, bpc_mask);
+        if (wmimax > (int)channel->state.wmidx) {
+            channel->state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
+    ASSERT(encoder->usr, channel->state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+static void FNAME(uncompress_row0_seg)(Encoder *encoder, Channel *channel, int i,
+                                       BYTE * const correlate_row,
+                                       PIXEL * const cur_row,
+                                       const int end,
+                                       const unsigned int waitmask,
+                                       const unsigned int bpc,
+                                       const unsigned int bpc_mask)
+{
+    int stopidx;
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (i == 0) {
+        unsigned int codewordlen;
+
+        correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel,
+                                                             correlate_row[-1])->bestcode,
+                                                 encoder->io_word, &codewordlen);
+        cur_row[0].a = (BYTE)family.xlatL2U[correlate_row[0]];
+        decode_eatbits(encoder, codewordlen);
+
+        if (channel->state.waitcnt) {
+            --channel->state.waitcnt;
+        } else {
+            channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
+            update_model(&channel->state, find_bucket(channel, correlate_row[-1]),
+                         correlate_row[0], bpc);
+        }
+        stopidx = ++i + channel->state.waitcnt;
+    } else {
+        stopidx = i + channel->state.waitcnt;
+    }
+
+    while (stopidx < end) {
+        struct s_bucket * pbucket = NULL;
+
+        for (; i <= stopidx; i++) {
+            unsigned int codewordlen;
+
+            pbucket = find_bucket(channel, correlate_row[i - 1]);
+            correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word,
+                                                     &codewordlen);
+            FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask);
+            decode_eatbits(encoder, codewordlen);
+        }
+
+        update_model(&channel->state, pbucket, correlate_row[stopidx], bpc);
+
+        stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
+    }
+
+    for (; i < end; i++) {
+        unsigned int codewordlen;
+
+        correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel,
+                                                             correlate_row[i - 1])->bestcode,
+                                                 encoder->io_word, &codewordlen);
+        FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask);
+        decode_eatbits(encoder, codewordlen);
+    }
+    channel->state.waitcnt = stopidx - end;
+}
+
+static void FNAME(uncompress_row0)(Encoder *encoder, Channel *channel,
+                                   PIXEL * const cur_row,
+                                   unsigned int width)
+
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    BYTE * const correlate_row = channel->correlate_row;
+    unsigned int pos = 0;
+
+    while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
+        if (channel->state.wmileft) {
+            FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row,
+                                       pos + channel->state.wmileft, bppmask[channel->state.wmidx],
+                                       bpc, bpc_mask);
+            pos += channel->state.wmileft;
+            width -= channel->state.wmileft;
+        }
+
+        channel->state.wmidx++;
+        set_wm_trigger(&channel->state);
+        channel->state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row, pos + width,
+                                   bppmask[channel->state.wmidx], bpc, bpc_mask);
+        if (wmimax > (int)channel->state.wmidx) {
+            channel->state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
+    ASSERT(encoder->usr, channel->state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+static void FNAME(uncompress_row_seg)(Encoder *encoder, Channel *channel,
+                                      BYTE *correlate_row,
+                                      const PIXEL * const prev_row,
+                                      PIXEL * const cur_row,
+                                      int i,
+                                      const int end,
+                                      const unsigned int bpc,
+                                      const unsigned int bpc_mask)
+{
+    const unsigned int waitmask = bppmask[channel->state.wmidx];
+    int stopidx;
+#ifdef RLE
+    int run_index = 0;
+    int run_end;
+#endif
+
+    ASSERT(encoder->usr, end - i > 0);
+
+    if (i == 0) {
+        unsigned int codewordlen;
+
+        correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel, correlate_row[-1])->bestcode,
+                                                             encoder->io_word, &codewordlen);
+        cur_row[0].a = (family.xlatL2U[correlate_row[0]] + prev_row[0].a) & bpc_mask;
+        decode_eatbits(encoder, codewordlen);
+
+        if (channel->state.waitcnt) {
+            --channel->state.waitcnt;
+        } else {
+            channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
+            update_model(&channel->state, find_bucket(channel, correlate_row[-1]),
+                         correlate_row[0], bpc);
+        }
+        stopidx = ++i + channel->state.waitcnt;
+    } else {
+        stopidx = i + channel->state.waitcnt;
+    }
+    for (;;) {
+        while (stopidx < end) {
+            struct s_bucket * pbucket = NULL;
+
+            for (; i <= stopidx; i++) {
+                unsigned int codewordlen;
+#ifdef RLE
+                RLE_PRED_1_IMP;
+                RLE_PRED_2_IMP;
+                RLE_PRED_3_IMP;
+#endif
+                pbucket = find_bucket(channel, correlate_row[i - 1]);
+                correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word,
+                                                         &codewordlen);
+                FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask);
+                decode_eatbits(encoder, codewordlen);
+            }
+
+            update_model(&channel->state, pbucket, correlate_row[stopidx], bpc);
+
+            stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
+        }
+
+        for (; i < end; i++) {
+            unsigned int codewordlen;
+#ifdef RLE
+            RLE_PRED_1_IMP;
+            RLE_PRED_2_IMP;
+            RLE_PRED_3_IMP;
+#endif
+            correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel,
+                                                                 correlate_row[i - 1])->bestcode,
+                                                     encoder->io_word, &codewordlen);
+            FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask);
+            decode_eatbits(encoder, codewordlen);
+        }
+
+        channel->state.waitcnt = stopidx - end;
+
+        return;
+
+#ifdef RLE
+do_run:
+        channel->state.waitcnt = stopidx - i;
+        run_index = i;
+#ifdef RLE_STAT
+        run_end = i + decode_channel_run(encoder, channel);
+#else
+        run_end = i + decode_run(encoder);
+#endif
+
+        for (; i < run_end; i++) {
+            cur_row[i].a = cur_row[i - 1].a;
+        }
+
+        if (i == end) {
+            return;
+        }
+
+        stopidx = i + channel->state.waitcnt;
+#endif
+    }
+}
+
+static void FNAME(uncompress_row)(Encoder *encoder, Channel *channel,
+                                  const PIXEL * const prev_row,
+                                  PIXEL * const cur_row,
+                                  unsigned int width)
+
+{
+    const unsigned int bpc = BPC;
+    const unsigned int bpc_mask = BPC_MASK;
+    BYTE * const correlate_row = channel->correlate_row;
+    unsigned int pos = 0;
+
+    while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
+        if (channel->state.wmileft) {
+            FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos,
+                                      pos + channel->state.wmileft, bpc, bpc_mask);
+            pos += channel->state.wmileft;
+            width -= channel->state.wmileft;
+        }
+
+        channel->state.wmidx++;
+        set_wm_trigger(&channel->state);
+        channel->state.wmileft = wminext;
+    }
+
+    if (width) {
+        FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos,
+                                  pos + width, bpc, bpc_mask);
+        if (wmimax > (int)channel->state.wmidx) {
+            channel->state.wmileft -= width;
+        }
+    }
+
+    ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
+    ASSERT(encoder->usr, channel->state.wmidx <= 32);
+    ASSERT(encoder->usr, wminext > 0);
+}
+
+#undef PIXEL
+#undef FNAME
+#undef _PIXEL_A
+#undef _PIXEL_B
+#undef _PIXEL_C
+#undef RLE_PRED_1_IMP
+#undef RLE_PRED_2_IMP
+#undef RLE_PRED_3_IMP
+#undef golomb_coding
+#undef golomb_deoding
+#undef update_model
+#undef find_bucket
+#undef family
+#undef BPC
+#undef BPC_MASK
+
diff --git a/display/qxldd.h b/display/qxldd.h
index 9283c43..a69c264 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -137,7 +137,7 @@ typedef struct UpdateTrace {
 
 typedef struct PMemSlot {
     MemSlot slot;
-    ADDRESS high_bits;
+    SPICE_ADDRESS high_bits;
 } PMemSlot;
 
 typedef struct DevResDynamic {
@@ -201,7 +201,7 @@ typedef struct PDev {
     FLONG blue_mask;
     ULONG fp_state_size;
 
-    PHYSICAL surf_phys;
+    QXLPHYSICAL surf_phys;
     UINT8 *surf_base;
 
     QuicData *quic_data;
@@ -231,7 +231,7 @@ typedef struct PDev {
     UINT8 main_mem_slot;
     UINT8 slot_id_bits;
     UINT8 slot_gen_bits;
-    ADDRESS va_slot_mask;
+    SPICE_ADDRESS va_slot_mask;
 
     UINT32 num_io_pages;
     UINT8 *io_pages_virt;
@@ -240,7 +240,7 @@ typedef struct PDev {
     UINT32 *dev_update_id;
 
     UINT32 update_area_port;
-    Rect *update_area;
+    SpiceRect *update_area;
 
     UINT32 *mm_clock;
 
diff --git a/display/res.c b/display/res.c
index 02ec6d7..4b1a2fd 100644
--- a/display/res.c
+++ b/display/res.c
@@ -29,14 +29,14 @@
 #define WAIT_FOR_EVENT(pdev, event, timeout) EngWaitForSingleObject(event, timeout)
 #endif
 
-static _inline PHYSICAL PA(PDev *pdev, PVOID virt, UINT8 slot_id)
+static _inline QXLPHYSICAL PA(PDev *pdev, PVOID virt, UINT8 slot_id)
 {
     PMemSlot *p_slot = &pdev->mem_slots[slot_id];
 
     return p_slot->high_bits | ((UINT64)virt - p_slot->slot.start_virt_addr);
 }
 
-static _inline UINT64 VA(PDev *pdev, PHYSICAL paddr, UINT8 slot_id)
+static _inline UINT64 VA(PDev *pdev, QXLPHYSICAL paddr, UINT8 slot_id)
 {
     UINT64 virt;
     PMemSlot *p_slot = &pdev->mem_slots[slot_id];
@@ -67,7 +67,7 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable);
 
 #define PUSH_CMD(pdev) do {                             \
     int notify;                                         \
-    RING_PUSH(pdev->cmd_ring, notify);                  \
+    SPICE_RING_PUSH(pdev->cmd_ring, notify);            \
     if (notify) {                                       \
         WRITE_PORT_UCHAR(pdev->notify_cmd_port, 0);     \
     }                                                   \
@@ -75,7 +75,7 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable);
 
 #define PUSH_CURSOR_CMD(pdev) do {                      \
     int notify;                                         \
-    RING_PUSH(pdev->cursor_ring, notify);               \
+    SPICE_RING_PUSH(pdev->cursor_ring, notify);         \
     if (notify) {                                       \
         WRITE_PORT_UCHAR(pdev->notify_cursor_port, 0);  \
     }                                                   \
@@ -143,7 +143,7 @@ static void WaitForCursorRing(PDev* pdev)
     DEBUG_PRINT((pdev, 9, "%s: 0x%lx\n", __FUNCTION__, pdev));
 
     for (;;) {
-        RING_PROD_WAIT(pdev->cursor_ring, wait);
+        SPICE_RING_PROD_WAIT(pdev->cursor_ring, wait);
 
         if (!wait) {
             break;
@@ -158,7 +158,7 @@ static void WaitForCursorRing(PDev* pdev)
             EngWaitForSingleObject(pdev->cursor_event, &timeout);
 #endif // (WINVER < 0x0501)
 
-            if (RING_IS_FULL(pdev->cursor_ring)) {
+            if (SPICE_RING_IS_FULL(pdev->cursor_ring)) {
                 DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
             }
         }
@@ -179,7 +179,7 @@ static void WaitForCmdRing(PDev* pdev)
     DEBUG_PRINT((pdev, 9, "%s: 0x%lx\n", __FUNCTION__, pdev));
 
     for (;;) {
-        RING_PROD_WAIT(pdev->cmd_ring, wait);
+        SPICE_RING_PROD_WAIT(pdev->cmd_ring, wait);
 
         if (!wait) {
             break;
@@ -194,7 +194,7 @@ static void WaitForCmdRing(PDev* pdev)
             EngWaitForSingleObject(pdev->display_event, &timeout);
 #endif // (WINVER < 0x0501)
 
-            if (RING_IS_FULL(pdev->cmd_ring)) {
+            if (SPICE_RING_IS_FULL(pdev->cmd_ring)) {
                 DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
             }
         }
@@ -227,14 +227,14 @@ static void WaitForReleaseRing(PDev* pdev)
     for (;;) {
         LARGE_INTEGER timeout;
 
-        if (RING_IS_EMPTY(pdev->release_ring)) {
+        if (SPICE_RING_IS_EMPTY(pdev->release_ring)) {
             QXLSleep(pdev, 10);
-            if (!RING_IS_EMPTY(pdev->release_ring)) {
+            if (!SPICE_RING_IS_EMPTY(pdev->release_ring)) {
                 break;
             }
             WRITE_PORT_UCHAR(pdev->notify_oom_port, 0);
         }
-        RING_CONS_WAIT(pdev->release_ring, wait);
+        SPICE_RING_CONS_WAIT(pdev->release_ring, wait);
 
         if (!wait) {
             break;
@@ -243,7 +243,7 @@ static void WaitForReleaseRing(PDev* pdev)
         timeout.QuadPart = -30 * 1000 * 10; //30ms
         WAIT_FOR_EVENT(pdev, pdev->display_event, &timeout);
 
-        if (RING_IS_EMPTY(pdev->release_ring)) {
+        if (SPICE_RING_IS_EMPTY(pdev->release_ring)) {
 #ifdef DBG
             DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
             DEBUG_PRINT((pdev, 0, "\tfree %d out %d path %d rect %d bits %d\n",
@@ -278,8 +278,8 @@ static void *AllocMem(PDev* pdev, size_t size)
             continue;
         }
         WaitForReleaseRing(pdev);
-        pdev->Res.free_outputs = *RING_CONS_ITEM(pdev->release_ring);
-        RING_POP(pdev->release_ring, notify);
+        pdev->Res.free_outputs = *SPICE_RING_CONS_ITEM(pdev->release_ring);
+        SPICE_RING_POP(pdev->release_ring, notify);
     }
     EngReleaseSemaphore(pdev->malloc_sem);
     ASSERT(pdev, ptr >= pdev->Res.mspace_start && ptr < pdev->Res.mspace_end);
@@ -481,14 +481,14 @@ void PushDrawable(PDev *pdev, QXLDrawable *drawable)
     QXLCommand *cmd;
 
     WaitForCmdRing(pdev);
-    cmd = RING_PROD_ITEM(pdev->cmd_ring);
+    cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
     cmd->type = QXL_CMD_DRAW;
     cmd->data = PA(pdev, drawable, pdev->main_mem_slot);
     PUSH_CMD(pdev);
 }
 
 _inline void GetSurfaceMemory(PDev *pdev, UINT32 x, UINT32 y, UINT32 depth, UINT8 **base_mem,
-                              PHYSICAL *phys_mem, UINT8 allocation_type)
+                              QXLPHYSICAL *phys_mem, UINT8 allocation_type)
 {
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
@@ -499,7 +499,7 @@ _inline void GetSurfaceMemory(PDev *pdev, UINT32 x, UINT32 y, UINT32 depth, UINT
     *phys_mem = PA(pdev, *base_mem, pdev->main_mem_slot);
 }
 
-BOOL QXLGetSurface(PDev *pdev, PHYSICAL *surface_phys, UINT32 x, UINT32 y, UINT32 depth,
+BOOL QXLGetSurface(PDev *pdev, QXLPHYSICAL *surface_phys, UINT32 x, UINT32 y, UINT32 depth,
                    UINT8 **base_mem, UINT8 allocation_type) {
     ASSERT(pdev, allocation_type == DEVICE_BITMAP_ALLOCATION_TYPE_SURF0);
     GetSurfaceMemory(pdev, x, y, depth, base_mem, surface_phys, allocation_type);
@@ -508,7 +508,7 @@ BOOL QXLGetSurface(PDev *pdev, PHYSICAL *surface_phys, UINT32 x, UINT32 y, UINT3
 
 static void FreePath(PDev *pdev, Resource *res)
 {
-    PHYSICAL chunk_phys;
+    QXLPHYSICAL chunk_phys;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
@@ -546,7 +546,7 @@ static void FreePath(PDev *pdev, Resource *res)
 
 #define PATH_PREALLOC_PONTS 20
 #define PATH_MAX_ALLOC_PONTS 128
-#define PATH_ALLOC_SIZE (sizeof(Resource) + sizeof(QXLPath) + sizeof(PathSeg) +\
+#define PATH_ALLOC_SIZE (sizeof(Resource) + sizeof(QXLPath) + sizeof(SpicePathSeg) +\
                          sizeof(POINTFIX) * PATH_PREALLOC_PONTS)
 
 
@@ -565,19 +565,19 @@ static void __GetPathCommon(PDev *pdev, PATHOBJ *path, QXLDataChunk **chunk_ptr,
     do {
         int pt_buf_size;
         UINT8 *pt_buf;
-        PathSeg *seg;
+        SpicePathSeg *seg;
 
         more = PATHOBJ_bEnum(path, &data);
         if (data.count == 0) {
             break;
         }
 
-        if (end - now < sizeof(PathSeg)) {
+        if (end - now < sizeof(SpicePathSeg)) {
             size_t alloc_size = MIN(data.count << 3, sizeof(POINTFIX) * PATH_MAX_ALLOC_PONTS);
-            alloc_size += sizeof(PathSeg);
+            alloc_size += sizeof(SpicePathSeg);
             NEW_DATA_CHUNK(page_counter, alloc_size);
         }
-        seg = (PathSeg*)now;
+        seg = (SpicePathSeg*)now;
         seg->flags = data.flags;
         seg->count = data.count;
         now = seg->data;
@@ -644,7 +644,7 @@ static Resource *__GetPath(PDev *pdev, PATHOBJ *path)
     return res;
 }
 
-BOOL QXLGetPath(PDev *pdev, QXLDrawable *drawable, PHYSICAL *path_phys, PATHOBJ *path)
+BOOL QXLGetPath(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *path_phys, PATHOBJ *path)
 {
     Resource *path_res;
     ASSERT(pdev, pdev && drawable && path_phys && path);
@@ -661,7 +661,7 @@ BOOL QXLGetPath(PDev *pdev, QXLDrawable *drawable, PHYSICAL *path_phys, PATHOBJ
 
 static void FreeClipRects(PDev *pdev, Resource *res)
 {
-    PHYSICAL chunk_phys;
+    QXLPHYSICAL chunk_phys;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
@@ -681,17 +681,17 @@ static void FreeClipRects(PDev *pdev, Resource *res)
 
 #define RECTS_NUM_PREALLOC 8
 #define RECTS_ALLOC_SIZE (sizeof(Resource) + sizeof(QXLClipRects) + \
-                          sizeof(Rect) * RECTS_NUM_PREALLOC)
+                          sizeof(SpiceRect) * RECTS_NUM_PREALLOC)
 #define RECTS_NUM_ALLOC 20
-#define RECTS_CHUNK_ALLOC_SIZE (sizeof(QXLDataChunk) + sizeof(Rect) * RECTS_NUM_ALLOC)
+#define RECTS_CHUNK_ALLOC_SIZE (sizeof(QXLDataChunk) + sizeof(SpiceRect) * RECTS_NUM_ALLOC)
 
 static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
 {
     Resource *res;
     QXLClipRects *rects;
     QXLDataChunk *chunk;
-    Rect *dest;
-    Rect *dest_end;
+    SpiceRect *dest;
+    SpiceRect *dest_end;
     int more;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
@@ -707,7 +707,7 @@ static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
     chunk->prev_chunk = 0;
     chunk->next_chunk = 0;
 
-    dest = (Rect *)chunk->data;
+    dest = (SpiceRect *)chunk->data;
     dest_end = dest + ((RECTS_ALLOC_SIZE - sizeof(Resource) - sizeof(QXLClipRects)) >> 4);
 
     CLIPOBJ_cEnumStart(clip, TRUE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
@@ -730,11 +730,11 @@ static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
                 chunk = (QXLDataChunk *)page;
                 chunk->data_size = 0;
                 chunk->next_chunk = 0;
-                dest = (Rect *)chunk->data;
+                dest = (SpiceRect *)chunk->data;
                 dest_end = dest + RECTS_NUM_ALLOC;
             }
             CopyRect(dest, now);
-            chunk->data_size += sizeof(Rect);
+            chunk->data_size += sizeof(SpiceRect);
         }
     } while (more);
     DEBUG_PRINT((pdev, 13, "%s: done, num_rects %d\n", __FUNCTION__, rects->num_rects));
@@ -748,7 +748,7 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable)
     DEBUG_PRINT((pdev, 9, "%s\n", __FUNCTION__));
 
     if (clip == NULL) {
-        drawable->clip.type = CLIP_TYPE_NONE;
+        drawable->clip.type = SPICE_CLIP_TYPE_NONE;
         DEBUG_PRINT((pdev, 10, "%s: QXL_CLIP_TYPE_NONE\n", __FUNCTION__));
         return TRUE;
     }
@@ -756,15 +756,15 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable)
     if (clip->iDComplexity == DC_RECT) {
         QXLClipRects *rects;
         rects_res = (Resource *)AllocMem(pdev, sizeof(Resource) + sizeof(QXLClipRects) +
-                                         sizeof(Rect));
+                                         sizeof(SpiceRect));
         rects_res->refs = 1;
         rects_res->free = FreeClipRects;
         rects = (QXLClipRects *)rects_res->res;
         rects->num_rects = 1;
-        rects->chunk.data_size = sizeof(Rect);
+        rects->chunk.data_size = sizeof(SpiceRect);
         rects->chunk.prev_chunk = 0;
         rects->chunk.next_chunk = 0;
-        CopyRect((Rect *)rects->chunk.data, &clip->rclBounds);
+        CopyRect((SpiceRect *)rects->chunk.data, &clip->rclBounds);
     } else {
 
         ASSERT(pdev, clip->iDComplexity == DC_COMPLEX);
@@ -780,7 +780,7 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable)
             EngDeletePath(path);
             DrawableAddRes(pdev, drawable, path_res);
             RELEASE_RES(pdev, path_res);
-            drawable->clip.type = CLIP_TYPE_PATH;
+            drawable->clip.type = SPICE_CLIP_TYPE_PATH;
             drawable->clip.data = PA(pdev, path_res->res, pdev->main_mem_slot);
             DEBUG_PRINT((pdev, 10, "%s: done\n", __FUNCTION__));
             return TRUE;
@@ -792,7 +792,7 @@ static BOOL SetClip(PDev *pdev, CLIPOBJ *clip, QXLDrawable *drawable)
 
     DrawableAddRes(pdev, drawable, rects_res);
     RELEASE_RES(pdev, rects_res);
-    drawable->clip.type = CLIP_TYPE_RECTS;
+    drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
     drawable->clip.data = PA(pdev, rects_res->res, pdev->main_mem_slot);
     DEBUG_PRINT((pdev, 10, "%s: done\n", __FUNCTION__));
     return TRUE;
@@ -933,8 +933,8 @@ static CacheImage *AllocCacheImage(PDev* pdev)
             continue;
         }
         WaitForReleaseRing(pdev);
-        pdev->Res.free_outputs = *RING_CONS_ITEM(pdev->release_ring);
-        RING_POP(pdev->release_ring, notify);
+        pdev->Res.free_outputs = *SPICE_RING_CONS_ITEM(pdev->release_ring);
+        SPICE_RING_POP(pdev->release_ring, notify);
     }
     RingRemove(pdev, item);
     return CONTAINEROF(item, CacheImage, lru_link);
@@ -964,7 +964,7 @@ typedef struct InternalPalette {
     UINT32 refs;
     struct InternalPalette *next;
     RingItem lru_link;
-    Palette palette;
+    SpicePalette palette;
 } InternalPalette;
 
 #define PALETTE_HASH_VAL(unique) ((int)(unique) & PALETTE_HASH_NASKE)
@@ -1053,7 +1053,7 @@ static _inline void PaletteCacheAdd(PDev *pdev, InternalPalette *palette)
 }
 
 
-static _inline void GetPallette(PDev *pdev, Bitmap *bitmap, XLATEOBJ *color_trans)
+static _inline void GetPallette(PDev *pdev, SpiceBitmap *bitmap, XLATEOBJ *color_trans)
 {
     InternalPalette *internal;
 
@@ -1085,7 +1085,7 @@ static _inline void GetPallette(PDev *pdev, Bitmap *bitmap, XLATEOBJ *color_tran
 static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
 {
     InternalImage *internal;
-    PHYSICAL chunk_phys;
+    QXLPHYSICAL chunk_phys;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
@@ -1111,13 +1111,13 @@ static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
 static _inline QuicImageType GetQuicImageType(UINT8 format)
 {
     switch (format) {
-    case BITMAP_FMT_32BIT:
+    case SPICE_BITMAP_FMT_32BIT:
         return QUIC_IMAGE_TYPE_RGB32;
-    case BITMAP_FMT_16BIT:
+    case SPICE_BITMAP_FMT_16BIT:
         return QUIC_IMAGE_TYPE_RGB16;
-    case BITMAP_FMT_RGBA:
+    case SPICE_BITMAP_FMT_RGBA:
         return QUIC_IMAGE_TYPE_RGBA;
-    case BITMAP_FMT_24BIT:
+    case SPICE_BITMAP_FMT_24BIT:
         return QUIC_IMAGE_TYPE_RGB24;
     default:
         return QUIC_IMAGE_TYPE_INVALID;
@@ -1209,7 +1209,7 @@ static _inline Resource *GetQuicImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color
 
     internal = (InternalImage *)image_res->res;
     SetImageId(internal, cache_me, width, height, format, key);
-    internal->image.descriptor.type = IMAGE_TYPE_QUIC;
+    internal->image.descriptor.type = SPICE_IMAGE_TYPE_QUIC;
     internal->image.descriptor.width = width;
     internal->image.descriptor.height = height;
 
@@ -1241,7 +1241,7 @@ static _inline Resource *GetQuicImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color
 static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
 {
     InternalImage *internal;
-    PHYSICAL chunk_phys;
+    QXLPHYSICAL chunk_phys;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
@@ -1252,8 +1252,8 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
     }
 
     if (internal->image.bitmap.palette) {
-        Palette *palette = (Palette *)VA(pdev, internal->image.bitmap.palette,
-                                         pdev->main_mem_slot);
+        SpicePalette *palette = (SpicePalette *)VA(pdev, internal->image.bitmap.palette,
+                                                   pdev->main_mem_slot);
         ReleasePalette(pdev, CONTAINEROF(palette, InternalPalette, palette));
     }
 
@@ -1299,7 +1299,7 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
 
     internal = (InternalImage *)image_res->res;
     SetImageId(internal, cache_me, width, height, format, key);
-    internal->image.descriptor.type = IMAGE_TYPE_BITMAP;
+    internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
     chunk = (QXLDataChunk *)(&internal->image.bitmap + 1);
     chunk->data_size = 0;
     chunk->prev_chunk = 0;
@@ -1343,17 +1343,17 @@ static _inline UINT32 GetHash(UINT8 *src, INT32 width, INT32 height, UINT8 forma
                                   hash_value);
     }
 
-    if (format == BITMAP_FMT_32BIT && stride == line_size) {
+    if (format == SPICE_BITMAP_FMT_32BIT && stride == line_size) {
         hash_value = murmurhash2ajump3((UINT32 *)row_buf, width * height, hash_value);
     } else {
         for (row = 0; row < height; row++) {
     #ifdef ADAPTIVE_HASH
-            if (format ==  BITMAP_FMT_32BIT) {
+            if (format ==  SPICE_BITMAP_FMT_32BIT) {
                 hash_value = murmurhash2ajump3((UINT32 *)row_buf, width, hash_value);
             } else {
-                if (format == BITMAP_FMT_4BIT_BE && (width & 0x1)) {
+                if (format == SPICE_BITMAP_FMT_4BIT_BE && (width & 0x1)) {
                     last_byte = row_buf[line_size - 1] & 0xF0;
-                } else if (format == BITMAP_FMT_1BIT_BE && (reminder = width & 0x7)) {
+                } else if (format == SPICE_BITMAP_FMT_1BIT_BE && (reminder = width & 0x7)) {
                     last_byte = row_buf[line_size - 1] & ~((1 << (8 - reminder)) - 1);
                 }
                 if (last_byte) {
@@ -1376,22 +1376,22 @@ static _inline UINT32 GetFormatLineSize(INT32 width, ULONG bitmap_format, UINT8
 {
     switch (bitmap_format) {
     case BMF_32BPP:
-        *format = BITMAP_FMT_32BIT;
+        *format = SPICE_BITMAP_FMT_32BIT;
         return width << 2;
     case BMF_24BPP:
-        *format = BITMAP_FMT_24BIT;
+        *format = SPICE_BITMAP_FMT_24BIT;
         return width * 3;
     case BMF_16BPP:
-        *format = BITMAP_FMT_16BIT;
+        *format = SPICE_BITMAP_FMT_16BIT;
         return width << 1;
     case BMF_8BPP:
-        *format = BITMAP_FMT_8BIT;
+        *format = SPICE_BITMAP_FMT_8BIT;
         return width;
     case BMF_4BPP:
-        *format = BITMAP_FMT_4BIT_BE;
+        *format = SPICE_BITMAP_FMT_4BIT_BE;
         return ALIGN(width, 2) >> 1;
     case BMF_1BPP:
-        *format = BITMAP_FMT_1BIT_BE;
+        *format = SPICE_BITMAP_FMT_1BIT_BE;
         return ALIGN(width, 8) >> 3;
     default:
         return 0;
@@ -1487,8 +1487,8 @@ static _inline UINT32 get_image_serial()
     return ret;
 }
 
-BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys, SURFOBJ *surf,
-                  Rect *area, XLATEOBJ *color_trans, UINT32 *hash_key, BOOL use_cache)
+BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SURFOBJ *surf,
+                  SpiceRect *area, XLATEOBJ *color_trans, UINT32 *hash_key, BOOL use_cache)
 {
     Resource *image_res;
     InternalImage *internal;
@@ -1608,8 +1608,8 @@ BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys, SURFO
     return TRUE;
 }
 
-BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys,
-                       SURFOBJ *surf, Rect *area)
+BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys,
+                       SURFOBJ *surf, SpiceRect *area)
 {
     Resource *image_res;
     InternalImage *internal;
@@ -1641,7 +1641,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys,
     }
 
     if (!ImageKeyGet(pdev, surf->hsurf, gdi_unique, &key)) {
-        key = GetHash(surf->pvScan0, surf->sizlBitmap.cx, surf->sizlBitmap.cy, BITMAP_FMT_RGBA,
+        key = GetHash(surf->pvScan0, surf->sizlBitmap.cx, surf->sizlBitmap.cy, SPICE_BITMAP_FMT_RGBA,
                       surf->sizlBitmap.cx << 2, surf->lDelta, NULL);
         ImageKeyPut(pdev, surf->hsurf, gdi_unique, key);
         DEBUG_PRINT((pdev, 11, "%s: ImageKeyPut %u\n", __FUNCTION__, key));
@@ -1649,7 +1649,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys,
         DEBUG_PRINT((pdev, 11, "%s: ImageKeyGet %u\n", __FUNCTION__, key));
     }
 
-    if (cache_image = ImageCacheGetByKey(pdev, key, TRUE, BITMAP_FMT_RGBA,
+    if (cache_image = ImageCacheGetByKey(pdev, key, TRUE, SPICE_BITMAP_FMT_RGBA,
                                          surf->sizlBitmap.cx, surf->sizlBitmap.cy)) {
         DEBUG_PRINT((pdev, 11, "%s: ImageCacheGetByKey %u hits %u\n", __FUNCTION__,
                      key, cache_image->hits));
@@ -1665,7 +1665,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys,
         ImageCacheRemove(pdev, cache_image);
         cache_image->key = key;
         cache_image->image = NULL;
-        cache_image->format = BITMAP_FMT_RGBA;
+        cache_image->format = SPICE_BITMAP_FMT_RGBA;
         cache_image->width = surf->sizlBitmap.cx;
         cache_image->height = surf->sizlBitmap.cy;
         ImageCacheAdd(pdev, cache_image);
@@ -1686,9 +1686,9 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys,
     }
 
     if (!(image_res = GetQuicImage(pdev, surf, NULL, !!cache_image, width, height,
-                                   BITMAP_FMT_RGBA, src, width << 2, key))) {
+                                   SPICE_BITMAP_FMT_RGBA, src, width << 2, key))) {
         image_res = GetBitmapImage(pdev, surf, NULL, !!cache_image, width, height,
-                                   BITMAP_FMT_RGBA, src, width << 2, key);
+                                   SPICE_BITMAP_FMT_RGBA, src, width << 2, key);
     }
     internal = (InternalImage *)image_res->res;
     if ((internal->cache = cache_image)) {
@@ -1704,7 +1704,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys,
     return TRUE;
 }
 
-BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, PHYSICAL *image_phys)
+BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, QXLPHYSICAL *image_phys)
 {
     InternalImage *internal;
     CacheImage *cache_image;
@@ -1720,10 +1720,10 @@ BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, PHY
     return FALSE;
 }
 
-BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, QMask *qxl_mask, SURFOBJ *mask, POINTL *pos,
+BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, SpiceQMask *qxl_mask, SURFOBJ *mask, POINTL *pos,
                 BOOL invers, LONG width, LONG height)
 {
-    Rect area;
+    SpiceRect area;
 
     if (!mask) {
         qxl_mask->bitmap = 0;
@@ -1736,7 +1736,7 @@ BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, QMask *qxl_mask, SURFOBJ *mas
         return FALSE;
     }
 
-    qxl_mask->flags = invers ? MASK_INVERS : 0;
+    qxl_mask->flags = invers ? SPICE_MASK_FLAGS_INVERS : 0;
 
     area.left = pos->x;
     area.right = area.left + width;
@@ -1757,7 +1757,7 @@ static void FreeBuf(PDev *pdev, Resource *res)
     FreeMem(pdev, res);
 }
 
-UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, PHYSICAL *buf_phys, UINT32 size)
+UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *buf_phys, UINT32 size)
 {
     Resource *buf_res;
 
@@ -1797,7 +1797,7 @@ void UpdateArea(PDev *pdev, RECTL *area)
     updat_cmd->update_id = ++pdev->Res.update_id;
 
     WaitForCmdRing(pdev);
-    cmd = RING_PROD_ITEM(pdev->cmd_ring);
+    cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
     cmd->type = QXL_CMD_UPDATE;
     cmd->data = PA(pdev, updat_cmd, pdev->main_mem_slot);
     PUSH_CMD(pdev);
@@ -1839,7 +1839,7 @@ void UpdateArea(PDev *pdev, RECTL *area)
 
 static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLYPHPOS *glyps,
                                     QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
-                                    UINT8 **end_ptr, int bpp, POINTL *delta, Point **str_pos)
+                                    UINT8 **end_ptr, int bpp, POINTL *delta, SpicePoint **str_pos)
 {
     GLYPHPOS *glyps_end = glyps + count;
     QXLDataChunk *chunk = *chunk_ptr;
@@ -1848,7 +1848,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     for (; glyps < glyps_end; glyps++) {
-        RasterGlyph *glyph;
+        SpiceRasterGlyph *glyph;
         UINT8 *line;
         UINT8 *end_line;
         UINT32 stride;
@@ -1857,7 +1857,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
             NEW_DATA_CHUNK(&pdev->Res.num_glyphs_pages, PAGE_SIZE);
         }
 
-        glyph = (RasterGlyph *)now;
+        glyph = (SpiceRasterGlyph *)now;
         if (delta) {
             if (*str_pos) {
                 glyph->render_pos.x = (*str_pos)->x + delta->x;
@@ -1911,7 +1911,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
 
 static _inline void add_vec_glyphs(PDev *pdev, QXLString *str, ULONG count, GLYPHPOS *glyps,
                                    QXLDataChunk **chunk_ptr, UINT8 **now_ptr, UINT8 **end_ptr,
-                                   POINTL *delta, Point  **str_pos)
+                                   POINTL *delta, SpicePoint  **str_pos)
 {
     GLYPHPOS *glyps_end = glyps + count;
     QXLDataChunk *chunk = *chunk_ptr;
@@ -1921,14 +1921,14 @@ static _inline void add_vec_glyphs(PDev *pdev, QXLString *str, ULONG count, GLYP
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
     for (; glyps < glyps_end; glyps++) {
-        VectotGlyph *glyph;
+        SpiceVectorGlyph *glyph;
 
         if (end - now < sizeof(*glyph)) {
             NEW_DATA_CHUNK(&pdev->Res.num_glyphs_pages, PAGE_SIZE);
         }
         chunk->data_size += sizeof(*glyph);
         str->data_size += sizeof(*glyph);
-        glyph = (VectotGlyph *)now;
+        glyph = (SpiceVectorGlyph *)now;
         now += sizeof(*glyph);
 
         if (delta) {
@@ -1958,11 +1958,11 @@ static _inline void add_vec_glyphs(PDev *pdev, QXLString *str, ULONG count, GLYP
 
 static _inline BOOL add_glyphs(PDev *pdev, QXLString *str, ULONG count, GLYPHPOS *glyps,
                                QXLDataChunk **chunk, UINT8 **now, UINT8 **end, POINTL *delta,
-                               Point  **str_pos)
+                               SpicePoint  **str_pos)
 {
-    if (str->flags & STRING_RASTER_A1) {
+    if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
         add_rast_glyphs(pdev, str, count, glyps, chunk, now, end, 1, delta, str_pos);
-    } else if (str->flags & STRING_RASTER_A4) {
+    } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
         add_rast_glyphs(pdev, str, count, glyps, chunk, now, end, 4, delta, str_pos);
     } else {
         DEBUG_PRINT((pdev, 0, "%s: vector: untested path, doing nothing!!!\n", __FUNCTION__));
@@ -1974,7 +1974,7 @@ static _inline BOOL add_glyphs(PDev *pdev, QXLString *str, ULONG count, GLYPHPOS
 
 static void FreeSring(PDev *pdev, Resource *res)
 {
-    PHYSICAL chunk_phys;
+    QXLPHYSICAL chunk_phys;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     chunk_phys = ((QXLString *)res->res)->chunk.next_chunk;
@@ -1994,7 +1994,7 @@ static void FreeSring(PDev *pdev, Resource *res)
 
 #define TEXT_ALLOC_SIZE sizeof(Resource) + sizeof(QXLString) + 512
 
-BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, PHYSICAL *str_phys, FONTOBJ *font, STROBJ *str)
+BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *str_phys, FONTOBJ *font, STROBJ *str)
 {
     Resource *str_res;
     QXLString *qxl_str;
@@ -2005,7 +2005,7 @@ BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, PHYSICAL *str_phys, FONTOBJ *f
     static int id_QXLGetStr = 0;
     POINTL  delta;
     POINTL  *delta_ptr;
-    Point  *str_pos;
+    SpicePoint  *str_pos;
 
     DEBUG_PRINT((pdev, 9, "%s\n", __FUNCTION__));
 
@@ -2020,8 +2020,8 @@ BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, PHYSICAL *str_phys, FONTOBJ *f
     qxl_str->flags = 0;
 
     if (font->flFontType & FO_TYPE_RASTER) {
-        qxl_str->flags = (font->flFontType & FO_GRAY16) ?   STRING_RASTER_A4 :
-                         STRING_RASTER_A1;
+        qxl_str->flags = (font->flFontType & FO_GRAY16) ?   SPICE_STRING_FLAGS_RASTER_A4 :
+                         SPICE_STRING_FLAGS_RASTER_A1;
     }
 
     chunk = &qxl_str->chunk;
@@ -2104,7 +2104,7 @@ void PushCursorCmd(PDev *pdev, QXLCursorCmd *cursor_cmd)
 
     DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
     WaitForCursorRing(pdev);
-    cmd = RING_PROD_ITEM(pdev->cursor_ring);
+    cmd = SPICE_RING_PROD_ITEM(pdev->cursor_ring);
     cmd->type = QXL_CMD_CURSOR;
     cmd->data = PA(pdev, cursor_cmd, pdev->main_mem_slot);
     PUSH_CURSOR_CMD(pdev);
@@ -2200,7 +2200,7 @@ static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
 
 static void FreeCursor(PDev *pdev, Resource *res)
 {
-    PHYSICAL chunk_phys;
+    QXLPHYSICAL chunk_phys;
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     chunk_phys = ((InternalCursor *)res->res)->cursor.chunk.next_chunk;
@@ -2265,7 +2265,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
     cursor->header.type = type;
     cursor->header.unique = unique ? ++pdev->Res.last_cursor_id : 0;
     cursor->header.width = (UINT16)surf->sizlBitmap.cx;
-    cursor->header.height = (type == CURSOR_TYPE_MONO) ? (UINT16)surf->sizlBitmap.cy >> 1 :
+    cursor->header.height = (type == SPICE_CURSOR_TYPE_MONO) ? (UINT16)surf->sizlBitmap.cy >> 1 :
                             (UINT16)surf->sizlBitmap.cy;
     cursor->header.hot_spot_x = (UINT16)hot_x;
     cursor->header.hot_spot_y = (UINT16)hot_y;
@@ -2281,23 +2281,23 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
     info->end = (UINT8 *)res + CURSOR_ALLOC_SIZE;
 
     switch (type) {
-    case CURSOR_TYPE_ALPHA:
-    case CURSOR_TYPE_COLOR32:
+    case SPICE_CURSOR_TYPE_ALPHA:
+    case SPICE_CURSOR_TYPE_COLOR32:
         line_size = cursor->header.width << 2;
         break;
-    case CURSOR_TYPE_MONO:
+    case SPICE_CURSOR_TYPE_MONO:
         line_size = ALIGN(cursor->header.width, 8) >> 3;
         break;
-    case CURSOR_TYPE_COLOR4:
+    case SPICE_CURSOR_TYPE_COLOR4:
         line_size = ALIGN(cursor->header.width, 2) >> 1;
         break;
-    case CURSOR_TYPE_COLOR8:
+    case SPICE_CURSOR_TYPE_COLOR8:
         line_size = cursor->header.width;
         break;
-    case CURSOR_TYPE_COLOR16:
+    case SPICE_CURSOR_TYPE_COLOR16:
         line_size = cursor->header.width << 1;
         break;
-    case CURSOR_TYPE_COLOR24:
+    case SPICE_CURSOR_TYPE_COLOR24:
         line_size = cursor->header.width * 3;
         break;
     }
@@ -2326,7 +2326,7 @@ BOOL GetAlphaCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
     ASSERT(pdev, surf->sizlBitmap.cx > 0 && surf->sizlBitmap.cy > 0);
 
     DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
-    GetCursorCommon(pdev, cmd, hot_x, hot_y, surf, CURSOR_TYPE_ALPHA, &info);
+    GetCursorCommon(pdev, cmd, hot_x, hot_y, surf, SPICE_CURSOR_TYPE_ALPHA, &info);
     DEBUG_PRINT((pdev, 8, "%s: done\n", __FUNCTION__));
     return TRUE;
 }
@@ -2341,7 +2341,7 @@ BOOL GetMonoCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFOB
 
     DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
 
-    GetCursorCommon(pdev, cmd, hot_x, hot_y, surf, CURSOR_TYPE_MONO, &info);
+    GetCursorCommon(pdev, cmd, hot_x, hot_y, surf, SPICE_CURSOR_TYPE_MONO, &info);
     DEBUG_PRINT((pdev, 8, "%s: done\n", __FUNCTION__));
     return TRUE;
 }
@@ -2371,19 +2371,19 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
     switch (surf->iBitmapFormat) {
     case BMF_32BPP:
-        type = CURSOR_TYPE_COLOR32;
+        type = SPICE_CURSOR_TYPE_COLOR32;
         break;
     case BMF_24BPP:
-        type = CURSOR_TYPE_COLOR24;
+        type = SPICE_CURSOR_TYPE_COLOR24;
         break;
     case BMF_16BPP:
-        type = CURSOR_TYPE_COLOR16;
+        type = SPICE_CURSOR_TYPE_COLOR16;
         break;
     case BMF_8BPP:
-        type = CURSOR_TYPE_COLOR8;
+        type = SPICE_CURSOR_TYPE_COLOR8;
         break;
     case BMF_4BPP:
-        type = CURSOR_TYPE_COLOR4;
+        type = SPICE_CURSOR_TYPE_COLOR4;
         break;
     default:
         DEBUG_PRINT((pdev, 0, "%s: unexpected format\n", __FUNCTION__));
@@ -2394,9 +2394,9 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
         UINT8 *src;
         UINT8 *src_end;
 
-        if (type == CURSOR_TYPE_COLOR8) {
+        if (type == SPICE_CURSOR_TYPE_COLOR8) {
 
-            DEBUG_PRINT((pdev, 8, "%s: CURSOR_TYPE_COLOR8\n", __FUNCTION__));
+            DEBUG_PRINT((pdev, 8, "%s: SPICE_CURSOR_TYPE_COLOR8\n", __FUNCTION__));
             ASSERT(pdev, color_trans);
             ASSERT(pdev, color_trans->pulXlate);
             ASSERT(pdev, color_trans->flXlate & XO_TABLE);
@@ -2415,7 +2415,7 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
                 }
             }
             info.cursor->data_size += 256 << 2;
-        } else if (type == CURSOR_TYPE_COLOR4) {
+        } else if (type == SPICE_CURSOR_TYPE_COLOR4) {
 
             ASSERT(pdev, color_trans);
             ASSERT(pdev, color_trans->pulXlate);
@@ -2471,7 +2471,7 @@ BOOL GetTransparentCursor(PDev *pdev, QXLCursorCmd *cmd)
     RingItemInit(&internal->lru_link);
 
     cursor = &internal->cursor;
-    cursor->header.type = CURSOR_TYPE_MONO;
+    cursor->header.type = SPICE_CURSOR_TYPE_MONO;
     cursor->header.unique = 0;
     cursor->header.width = 0;
     cursor->header.height = 0;
diff --git a/display/res.h b/display/res.h
index 18ae081..bc18d1f 100644
--- a/display/res.h
+++ b/display/res.h
@@ -25,20 +25,20 @@ UINT64 ReleaseOutput(PDev *pdev, UINT64 output_id);
 QXLDrawable *Drawable(PDev *pdev, UINT8 type, RECTL *area, CLIPOBJ *clip);
 void PushDrawable(PDev *pdev, QXLDrawable *drawable);
 
-BOOL QXLGetSurface(PDev *pdev, PHYSICAL *surface_phys, UINT32 x, UINT32 y, UINT32 depth,
+BOOL QXLGetSurface(PDev *pdev, QXLPHYSICAL *surface_phys, UINT32 x, UINT32 y, UINT32 depth,
                     UINT8 **base_mem, UINT8 allocation_type);
-BOOL QXLGetPath(PDev *pdev, QXLDrawable *drawable, PHYSICAL *path_phys, PATHOBJ *path);
-BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, QMask *qxl_mask, SURFOBJ *mask, POINTL *pos,
+BOOL QXLGetPath(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *path_phys, PATHOBJ *path);
+BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, SpiceQMask *qxl_mask, SURFOBJ *mask, POINTL *pos,
                 BOOL invers, LONG width, LONG height);
-BOOL QXLGetBrush(PDev *pdev, QXLDrawable *drawable, Brush *qxl_brush,
+BOOL QXLGetBrush(PDev *pdev, QXLDrawable *drawable, SpiceBrush *qxl_brush,
                             BRUSHOBJ *brush, POINTL *brush_pos);
-BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys, SURFOBJ *surf,
-                  Rect *area, XLATEOBJ *color_trans, UINT32 *hash_key, BOOL use_cache);
-BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, PHYSICAL *image_phys);
-BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *image_phys, SURFOBJ *surf,
-                       Rect *area);
-UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, PHYSICAL *buf_phys, UINT32 size);
-BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, PHYSICAL *str_phys, FONTOBJ *font, STROBJ *str);
+BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SURFOBJ *surf,
+                  SpiceRect *area, XLATEOBJ *color_trans, UINT32 *hash_key, BOOL use_cache);
+BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, QXLPHYSICAL *image_phys);
+BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SURFOBJ *surf,
+                       SpiceRect *area);
+UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *buf_phys, UINT32 size);
+BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *str_phys, FONTOBJ *font, STROBJ *str);
 
 void UpdateArea(PDev *pdev, RECTL *area);
 
diff --git a/display/rop.c b/display/rop.c
index 73b80b1..b9b25b8 100644
--- a/display/rop.c
+++ b/display/rop.c
@@ -37,26 +37,30 @@ enum ROP3type {
 
 
 ROP3Info rops2[] = {
-    {QXL_EFFECT_OPAQUE, 0, ROP3_TYPE_BLACKNESS, ROPD_OP_BLACKNESS},                           //0
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_OR | ROPD_INVERS_RES}, //DPon
+    {QXL_EFFECT_OPAQUE, 0, ROP3_TYPE_BLACKNESS, SPICE_ROPD_OP_BLACKNESS},                     //0
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_OR |
+                                                               SPICE_ROPD_INVERS_RES},        //DPon
     {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
-                                               ROPD_INVERS_BRUSH | ROPD_OP_AND},              //DPna
-    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_INVERS_BRUSH | ROPD_OP_PUT},         //Pn
+                                               SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_AND},  //DPna
+    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_INVERS_BRUSH |
+                                                    SPICE_ROPD_OP_PUT},                       //Pn
     {QXL_EFFECT_BLACKNESS_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
-                                                            ROPD_INVERS_DEST | ROPD_OP_AND},  //PDna
-    {QXL_EFFECT_REVERT_ON_DUP, ROP3_DEST, ROP3_TYPE_INVERS, ROPD_OP_INVERS},                  //Dn
-    {QXL_EFFECT_REVERT_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_XOR},          //DPx
+                                              SPICE_ROPD_INVERS_DEST | SPICE_ROPD_OP_AND},    //PDna
+    {QXL_EFFECT_REVERT_ON_DUP, ROP3_DEST, ROP3_TYPE_INVERS, SPICE_ROPD_OP_INVERS},            //Dn
+    {QXL_EFFECT_REVERT_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_XOR},    //DPx
     {QXL_EFFECT_BLACKNESS_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
-                                                     ROPD_OP_AND | ROPD_INVERS_RES},          //DPan
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_AND},             //DPa
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_XOR | ROPD_INVERS_RES},//DPxn
+                                              SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_RES},     //DPan
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_AND},       //DPa
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_XOR |
+                                               SPICE_ROPD_INVERS_RES},                        //DPxn
     {QXL_EFFECT_NOP, ROP3_DEST, ROP3_TYPE_NOP, 0},                                            //D
     {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
-                                            ROPD_INVERS_BRUSH | ROPD_OP_OR},                  //DPno
-    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_PUT},                             //P
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_INVERS_DEST | ROPD_OP_OR},//PDno
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_OR},              //DPo
-    {QXL_EFFECT_OPAQUE, 0, ROP3_TYPE_WHITENESS, ROPD_OP_WHITENESS},                           //1
+                                            SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_OR},      //DPno
+    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_PUT},                       //P
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_INVERS_DEST |
+                                               SPICE_ROPD_OP_OR},                             //PDno
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_OR},        //DPo
+    {QXL_EFFECT_OPAQUE, 0, ROP3_TYPE_WHITENESS, SPICE_ROPD_OP_WHITENESS},                     //1
 };
 
 
@@ -68,27 +72,32 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x01},                             //DPSoon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x02},                             //DPSona
                                                                                     //PSon
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_OP_OR | ROPD_INVERS_RES},
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_OP_OR |
+                                               SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x04},                             //SDPona
                                                                                     //DPon
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_OR | ROPD_INVERS_RES},
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_OR |
+                                               SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x06},                             //PDSxnon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x07},                             //PDSaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x08},                             //SDPnaa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x09},                             //PDSxon
                                                                                     //DPna
     {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
-                                                                   ROPD_INVERS_BRUSH | ROPD_OP_AND},
+                                                                   SPICE_ROPD_INVERS_BRUSH |
+                                                                   SPICE_ROPD_OP_AND},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x0b},                             //PSDnaon
                                                                                     //SPna
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_INVERS_BRUSH | ROPD_OP_AND },
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_INVERS_BRUSH |
+                                                                 SPICE_ROPD_OP_AND },
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x0d},                             //PDSnaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x0e},                             //PDSonon
                                                                                     //Pn
-    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_INVERS_BRUSH | ROPD_OP_PUT},
+    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_PUT},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x10},                             //PDSona
                                                                                     //DSon
-    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_OP_OR | ROPD_INVERS_RES},
+    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, SPICE_ROPD_OP_OR |
+                                             SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x12},                             //SDPxnon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x13},                             //SDPaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x14},                             //DPSxnon
@@ -106,7 +115,8 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x20},                             //DPSnaa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x21},                             //SDPxon
                                                                                     //DSna
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_INVERS_SRC | ROPD_OP_AND},
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, SPICE_ROPD_INVERS_SRC |
+                                                                   SPICE_ROPD_OP_AND},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x23},                             //SPDnaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x24},                             //SPxDSxa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x25},                             //PDSPanaxn
@@ -121,10 +131,12 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x2e},                             //PSDPxox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x2f},                             //PSDnoan
                                                                                     //PSna
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_INVERS_SRC | ROPD_OP_AND},
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_INVERS_SRC |
+                                                                 SPICE_ROPD_OP_AND},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x31},                             //SDPnaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x32},                             //SDPSoox
-    {QXL_EFFECT_OPAQUE, ROP3_SRC, ROP3_TYPE_COPY, ROPD_INVERS_SRC | ROPD_OP_PUT},   //Sn
+    {QXL_EFFECT_OPAQUE, ROP3_SRC, ROP3_TYPE_COPY, SPICE_ROPD_INVERS_SRC |
+                                                  SPICE_ROPD_OP_PUT},               //Sn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x34},                             //SPDSaox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x35},                             //SPDSxnox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x36},                             //SDPox
@@ -133,17 +145,19 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x39},                             //SPDnox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x3a},                             //SPDSxox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x3b},                             //SPDnoan
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_OP_XOR},      //PSx
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_OP_XOR},//PSx
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x3d},                             //SPDSonox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x3e},                             //SPDSnaox
                                                                                     //PSan
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_OP_AND | ROPD_INVERS_RES},
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_OP_AND |
+                                                                 SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x40},                             //PSDnaa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x41},                             //DPSxon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x42},                             //SDxPDxa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x43},                             //SPDSanaxn
                                                                                     //SDna
-    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_INVERS_DEST | ROPD_OP_AND},
+    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, SPICE_ROPD_INVERS_DEST |
+                                                              SPICE_ROPD_OP_AND},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x45},                             //DPSnaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x46},                             //DSPDaox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x47},                             //PSDPxaxn
@@ -156,7 +170,8 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x4e},                             //PDSPxox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x4f},                             //PDSnoan
                                                                                     //PDna
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_INVERS_DEST | ROPD_OP_AND},
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_INVERS_DEST |
+                                                               SPICE_ROPD_OP_AND},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x51},                             //DSPnaon
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x52},                             //DPSDaox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x53},                             //SPDSxaxn
@@ -166,20 +181,23 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x57},                             //DPSoan
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x58},                             //PDSPoax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x59},                             //DPSnox
-    {QXL_EFFECT_REVERT_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_XOR},//DPx
+    {QXL_EFFECT_REVERT_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_XOR},
+                                                                                    //DPx
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x5b},                             //DPSDonox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x5c},                             //DPSDxox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x5d},                             //DPSnoan
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x5e},                             //DPSDnaox
                                                                                     //DPan
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_AND | ROPD_INVERS_RES},
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_AND |
+                                                               SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x60},                             //PDSxa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x61},                             //DSPDSaoxxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x62},                             //DSPDoax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x63},                             //SDPnox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x64},                             //SDPSoax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x65},                             //DSPnox
-    {QXL_EFFECT_REVERT_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_OP_XOR}, //DSx
+    {QXL_EFFECT_REVERT_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND,
+                                                     SPICE_ROPD_OP_XOR},            //DSx
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x67},                             //SDPSonox
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x68},                             //DSPDSonoxxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x69},                             //PDSxxn
@@ -197,7 +215,8 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x75},                             //DSPnoan
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x76},                             //SDPSnaox
                                                                                     //DSan
-    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_OP_AND | ROPD_INVERS_RES},
+    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, SPICE_ROPD_OP_AND |
+                                                              SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x78},                             //PDSax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x79},                             //DSPDSoaxxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x7a},                             //DPSDnoax
@@ -214,7 +233,8 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x85},                             //PDSPnoaxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x86},                             //DSPDSoaxx
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x87},                             //PDSaxn
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_OP_AND},    //DSa
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND,
+                                                  SPICE_ROPD_OP_AND},               //DSa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x89},                             //SDPSnaoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x8a},                             //DSPnoa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x8b},                             //DSPDxoxn
@@ -232,20 +252,23 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x97},                             //PSDPSonoxx
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x98},                             //SDPSonoxn
                                                                                     //DSxn
-    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_OP_XOR | ROPD_INVERS_RES},
+    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, SPICE_ROPD_OP_XOR |
+                                                              SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x9a},                             //DPSnax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x9b},                             //SDPSoaxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x9c},                             //SPDnax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x9d},                             //DSPDoaxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x9e},                             //DSPDSaoxx
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0x9f},                             //PDSxan
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_AND},   //DPa
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
+                                                    SPICE_ROPD_OP_AND},             //DPa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa1},                             //PDSPnaoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa2},                             //DPSnoa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa3},                             //DPSDxoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa4},                             //PDSPonoxn
                                                                                     //PDxn
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_XOR | ROPD_INVERS_RES},
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_XOR |
+                                                               SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa6},                             //DSPnax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa7},                             //PDSPoaxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xa8},                             //DPSoa
@@ -256,7 +279,8 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xad},                             //DPSDaoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xae},                             //DSPnao
                                                                                     //DPno
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_INVERS_BRUSH | ROPD_OP_OR},
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
+                                                    SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_OR},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xb0},                             //PDSnoa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xb1},                             //PDSPxoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xb2},                             //SSPxDSxox
@@ -269,16 +293,18 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xb9},                             //DSPDaoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xba},                             //DPSnao
                                                                                     //DSno
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_INVERS_SRC | ROPD_OP_OR},
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND,
+                                                       SPICE_ROPD_INVERS_SRC | SPICE_ROPD_OP_OR},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xbc},                             //SPDSanax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xbd},                             //SDxPDxan
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xbe},                             //DPSxo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xbf},                             //DPSano
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_OP_AND},      //PSa
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_OP_AND},//PSa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xc1},                             //SPDSnaoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xc2},                             //SPDSonoxn
                                                                                     //PSxn
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_OP_XOR | ROPD_INVERS_RES},
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_OP_XOR |
+                                                                 SPICE_ROPD_INVERS_RES},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xc4},                             //SPDnoa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xc5},                             //SPDSxoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xc6},                             //SDPnax
@@ -287,11 +313,13 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xc9},                             //SPDoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xca},                             //DPSDxax
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xcb},                             //SPDSaoxn
-    {QXL_EFFECT_OPAQUE, ROP3_SRC, ROP3_TYPE_COPY, ROPD_OP_PUT},                     //S
+    {QXL_EFFECT_OPAQUE, ROP3_SRC, ROP3_TYPE_COPY, SPICE_ROPD_OP_PUT},                     //S
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xcd},                             //SDPono
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xce},                             //SDPnao
                                                                                     //SPno
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_INVERS_BRUSH | ROPD_OP_OR},
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE,
+                                               SPICE_ROPD_INVERS_BRUSH |
+                                               SPICE_ROPD_OP_OR},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xd0},                             //PSDnoa
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xd1},                             //PSDPxoxn
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xd2},                             //PDSnax
@@ -306,7 +334,9 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xdb},                             //SPxDSxan
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xdc},                             //SPDnao
                                                                                     //SDno
-    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_INVERS_DEST | ROPD_OP_OR},
+    {QXL_EFFECT_BLEND, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND,
+                                             SPICE_ROPD_INVERS_DEST |
+                                             SPICE_ROPD_OP_OR},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xde},                             //SDPxo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xdf},                             //SDPano
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xe0},                             //PDSoa
@@ -323,23 +353,29 @@ ROP3Info rops3[] = {
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xeb},                             //DPSxno
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xec},                             //SDPao
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xed},                             //SDPxno
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND, ROPD_OP_OR},     //DSo
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_SRC | ROP3_DEST, ROP3_TYPE_BLEND,
+                                                  SPICE_ROPD_OP_OR},                //DSo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xef},                             //SDPnoo
-    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_PUT},                   //P
+    {QXL_EFFECT_OPAQUE, ROP3_BRUSH, ROP3_TYPE_FILL, SPICE_ROPD_OP_PUT},                   //P
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf1},                             //PDSono
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf2},                             //PDSnao
                                                                                     //PSno
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_INVERS_SRC | ROPD_OP_OR},
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE,
+                                               SPICE_ROPD_INVERS_SRC |
+                                               SPICE_ROPD_OP_OR},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf4},                             //PSDnao
                                                                                     //PDno
-    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_INVERS_DEST | ROPD_OP_OR},
+    {QXL_EFFECT_BLEND, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
+                                               SPICE_ROPD_INVERS_DEST |
+                                               SPICE_ROPD_OP_OR},
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf6},                             //PDSxo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf7},                             //PDSano
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf8},                             //PDSao
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xf9},                             //PDSxno
-    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL, ROPD_OP_OR},    //DPo
+    {QXL_EFFECT_NOP_ON_DUP, ROP3_DEST | ROP3_BRUSH, ROP3_TYPE_FILL,
+                                                    SPICE_ROPD_OP_OR},              //DPo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xfb},                             //DPSnoo
-    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, ROPD_OP_OR},       //PSo
+    {QXL_EFFECT_OPAQUE, ROP3_SRC | ROP3_BRUSH, ROP3_TYPE_OPAQUE, SPICE_ROPD_OP_OR}, //PSo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xfd},                             //PSDnoo
     {QXL_EFFECT_BLEND, ROP3_ALL, ROP3_TYPE_ROP3, 0xfe},                             //DPSoo
     {QXL_EFFECT_OPAQUE, 0, ROP3_TYPE_WHITENESS, 1},                                 //1
@@ -373,8 +409,8 @@ static BOOL DoFill(PDev *pdev, RECTL *area, CLIPOBJ *clip, BRUSHOBJ *brush, POIN
     return TRUE;
 }
 
-static BOOL GetBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *bitmap_phys, SURFOBJ *surf,
-                      Rect *area, XLATEOBJ *color_trans, BOOL use_cache)
+static BOOL GetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *bitmap_phys, SURFOBJ *surf,
+                      SpiceRect *area, XLATEOBJ *color_trans, BOOL use_cache)
 {
     DEBUG_PRINT((pdev, 9, "%s\n", __FUNCTION__));
     if (surf->iType != STYPE_BITMAP) {
@@ -395,7 +431,8 @@ static BOOL GetBitmap(PDev *pdev, QXLDrawable *drawable, PHYSICAL *bitmap_phys,
 
 static _inline UINT8 GdiScaleModeToQxl(ULONG scale_mode)
 {
-    return (scale_mode == HALFTONE) ? IMAGE_SCALE_INTERPOLATE : IMAGE_SCALE_NEAREST;
+    return (scale_mode == HALFTONE) ? SPICE_IMAGE_SCALE_MODE_INTERPOLATE :
+                                      SPICE_IMAGE_SCALE_MODE_NEAREST;
 }
 
 static BOOL DoOpaque(PDev *pdev, RECTL *area, CLIPOBJ *clip, SURFOBJ *src, RECTL *src_rect,
diff --git a/display/surface.c b/display/surface.c
index c562ea7..36ae44c 100644
--- a/display/surface.c
+++ b/display/surface.c
@@ -70,7 +70,7 @@ VOID FreeDrawArea(DrawArea *drawarea)
     EngDeleteSurface(drawarea->bitmap);
 }
 
-HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, PHYSICAL *phys_mem,
+HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, QXLPHYSICAL *phys_mem,
                            UINT8 **base_mem, UINT8 allocation_type)
 {
     UINT8 depth;
diff --git a/display/surface.h b/display/surface.h
index 92ab5fd..a384020 100644
--- a/display/surface.h
+++ b/display/surface.h
@@ -13,7 +13,7 @@ typedef struct DrawArea {
 BOOL CreateDrawArea(PDev *pdev, DrawArea *drawarea, UINT8 *base_mem, UINT32 cx, UINT32 cy);
 VOID FreeDrawArea(DrawArea *drawarea);
 
-HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, PHYSICAL *phys_mem,
+HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, QXLPHYSICAL *phys_mem,
                            UINT8 **base_mem, UINT8 allocation_type);
 VOID DeleteDeviceBitmap(HSURF surf);
 
diff --git a/display/text.c b/display/text.c
index 261c0c7..c661544 100644
--- a/display/text.c
+++ b/display/text.c
@@ -72,10 +72,10 @@ BOOL APIENTRY DrvTextOut(SURFOBJ *surf, STROBJ *str, FONTOBJ *font, CLIPOBJ *cli
             goto error;
         }
         CopyRect(&drawable->u.text.back_area, &area);
-        drawable->u.text.back_mode = ROPD_OP_PUT;
+        drawable->u.text.back_mode = SPICE_ROPD_OP_PUT;
         drawable->effect = QXL_EFFECT_OPAQUE;
     } else {
-        drawable->u.text.back_brush.type = BRUSH_TYPE_NONE;
+        drawable->u.text.back_brush.type = SPICE_BRUSH_TYPE_NONE;
         RtlZeroMemory(&drawable->u.text.back_area, sizeof(drawable->u.text.back_area));
         drawable->u.text.back_mode = 0;
         drawable->effect = QXL_EFFECT_BLEND;
@@ -85,7 +85,7 @@ BOOL APIENTRY DrvTextOut(SURFOBJ *surf, STROBJ *str, FONTOBJ *font, CLIPOBJ *cli
     back_rop = &rops2[((mix >> 8) - 1) & 0x0f];
 
     if (!((fore_rop->flags | back_rop->flags) & ROP3_BRUSH)) {
-        drawable->u.stroke.brush.type = BRUSH_TYPE_NONE;
+        drawable->u.stroke.brush.type = SPICE_BRUSH_TYPE_NONE;
     } else if (!QXLGetBrush(pdev, drawable, &drawable->u.text.fore_brush, fore_brush,
                             brushs_origin)) {
         DEBUG_PRINT((pdev, 0, "%s: get brush failed\n", __FUNCTION__));
diff --git a/include/qxl_driver.h b/include/qxl_driver.h
index 8391f4a..12f5aac 100644
--- a/include/qxl_driver.h
+++ b/include/qxl_driver.h
@@ -18,7 +18,7 @@
 #ifndef _H_QXL_DRIVER
 #define _H_QXL_DRIVER
 
-#include "qxl_dev.h"
+#include <spice\qxl_dev.h>
 
 #if (WINVER < 0x0501)
 #include "wdmhelper.h"
@@ -65,7 +65,7 @@ typedef struct QXLDriverInfo {
     UINT32 *compression_level;
 
     UINT32 update_area_port;
-    Rect *update_area;
+    SpiceRect *update_area;
 
     UINT32 *mm_clock;
 
diff --git a/include/stdint.h b/include/stdint.h
new file mode 100644
index 0000000..8b94f37
--- /dev/null
+++ b/include/stdint.h
@@ -0,0 +1,394 @@
+/* ISO C9x  7.18  Integer types <stdint.h>
+
+ * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
+
+ *
+
+ *  THIS SOFTWARE IS NOT COPYRIGHTED
+
+ *
+
+ *  Contributor: Danny Smith <danny_r_smith_2001 at yahoo.co.nz>
+
+ *
+
+ *  This source code is offered for use in the public domain. You may
+
+ *  use, modify or distribute it freely.
+
+ *
+
+ *  This code is distributed in the hope that it will be useful but
+
+ *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+
+ *  DISCLAIMED. This includes but is not limited to warranties of
+
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ *
+
+ *  Date: 2000-12-02
+
+ */
+
+
+
+
+
+#ifndef _STDINT_H
+
+#define _STDINT_H
+
+#define __need_wint_t
+
+#define __need_wchar_t
+
+#include <stddef.h>
+
+
+
+#ifdef _WIN32_WCE
+
+typedef _int64 int64_t;
+
+typedef unsigned _int64 uint64_t;
+
+#else
+
+typedef long long  int64_t;
+
+typedef unsigned long long   uint64_t;
+
+#endif /* _WIN32_WCE */
+
+
+
+/* 7.18.1.1  Exact-width integer types */
+
+typedef signed char int8_t;
+
+typedef unsigned char   uint8_t;
+
+typedef short  int16_t;
+
+typedef unsigned short  uint16_t;
+
+typedef int  int32_t;
+
+typedef unsigned   uint32_t;
+
+
+
+/* 7.18.1.2  Minimum-width integer types */
+
+typedef signed char int_least8_t;
+
+typedef unsigned char   uint_least8_t;
+
+typedef short  int_least16_t;
+
+typedef unsigned short  uint_least16_t;
+
+typedef int  int_least32_t;
+
+typedef unsigned   uint_least32_t;
+
+#ifndef _WIN32_WCE
+
+typedef long long  int_least64_t;
+
+typedef unsigned long long   uint_least64_t;
+
+#endif
+
+
+
+/*  7.18.1.3  Fastest minimum-width integer types 
+
+ *  Not actually guaranteed to be fastest for all purposes
+
+ *  Here we use the exact-width types for 8 and 16-bit ints. 
+
+ */
+
+typedef char int_fast8_t;
+
+typedef unsigned char uint_fast8_t;
+
+typedef short  int_fast16_t;
+
+typedef unsigned short  uint_fast16_t;
+
+typedef int  int_fast32_t;
+
+typedef unsigned  int  uint_fast32_t;
+
+#ifndef _WIN32_WCE
+
+typedef long long  int_fast64_t;
+
+typedef unsigned long long   uint_fast64_t;
+
+#endif
+
+
+
+/* 7.18.1.4  Integer types capable of holding object pointers */
+
+typedef int intptr_t;
+
+typedef unsigned uintptr_t;
+
+
+
+/* 7.18.1.5  Greatest-width integer types */
+
+#ifndef _WIN32_WCE
+
+typedef long long  intmax_t;
+
+typedef unsigned long long   uintmax_t;
+
+#endif
+
+
+
+/* 7.18.2  Limits of specified-width integer types */
+
+#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS)
+
+
+
+/* 7.18.2.1  Limits of exact-width integer types */
+
+#define INT8_MIN (-128) 
+
+#define INT16_MIN (-32768)
+
+#define INT32_MIN (-2147483647 - 1)
+
+#define INT64_MIN  (-9223372036854775807LL - 1)
+
+
+
+#define INT8_MAX 127
+
+#define INT16_MAX 32767
+
+#define INT32_MAX 2147483647
+
+#define INT64_MAX 9223372036854775807LL
+
+
+
+#define UINT8_MAX 0xff /* 255U */
+
+#define UINT16_MAX 0xffff /* 65535U */
+
+#define UINT32_MAX 0xffffffff  /* 4294967295U */
+
+#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
+
+
+
+/* 7.18.2.2  Limits of minimum-width integer types */
+
+#define INT_LEAST8_MIN INT8_MIN
+
+#define INT_LEAST16_MIN INT16_MIN
+
+#define INT_LEAST32_MIN INT32_MIN
+
+#define INT_LEAST64_MIN INT64_MIN
+
+
+
+#define INT_LEAST8_MAX INT8_MAX
+
+#define INT_LEAST16_MAX INT16_MAX
+
+#define INT_LEAST32_MAX INT32_MAX
+
+#define INT_LEAST64_MAX INT64_MAX
+
+
+
+#define UINT_LEAST8_MAX UINT8_MAX
+
+#define UINT_LEAST16_MAX UINT16_MAX
+
+#define UINT_LEAST32_MAX UINT32_MAX
+
+#define UINT_LEAST64_MAX UINT64_MAX
+
+
+
+/* 7.18.2.3  Limits of fastest minimum-width integer types */
+
+#define INT_FAST8_MIN INT8_MIN
+
+#define INT_FAST16_MIN INT16_MIN
+
+#define INT_FAST32_MIN INT32_MIN
+
+#define INT_FAST64_MIN INT64_MIN
+
+
+
+#define INT_FAST8_MAX INT8_MAX
+
+#define INT_FAST16_MAX INT16_MAX
+
+#define INT_FAST32_MAX INT32_MAX
+
+#define INT_FAST64_MAX INT64_MAX
+
+
+
+#define UINT_FAST8_MAX UINT8_MAX
+
+#define UINT_FAST16_MAX UINT16_MAX
+
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define UINT_FAST64_MAX UINT64_MAX
+
+
+
+/* 7.18.2.4  Limits of integer types capable of holding
+
+    object pointers */ 
+
+#define INTPTR_MIN INT32_MIN
+
+#define INTPTR_MAX INT32_MAX
+
+#define UINTPTR_MAX UINT32_MAX
+
+
+
+/* 7.18.2.5  Limits of greatest-width integer types */
+
+#define INTMAX_MIN INT64_MIN
+
+#define INTMAX_MAX INT64_MAX
+
+#define UINTMAX_MAX UINT64_MAX
+
+
+
+/* 7.18.3  Limits of other integer types */
+
+#define PTRDIFF_MIN INT32_MIN
+
+#define PTRDIFF_MAX INT32_MAX
+
+
+
+#define SIG_ATOMIC_MIN INT32_MIN
+
+#define SIG_ATOMIC_MAX INT32_MAX
+
+
+
+#define SIZE_MAX UINT32_MAX
+
+
+
+#ifndef WCHAR_MIN  /* also in wchar.h */ 
+
+#define WCHAR_MIN 0
+
+#define WCHAR_MAX 0xffff /* UINT16_MAX */
+
+#endif
+
+
+
+/*
+
+ * wint_t is unsigned short for compatibility with MS runtime
+
+ */
+
+#define WINT_MIN 0
+
+#define WINT_MAX 0xffff /* UINT16_MAX */
+
+
+
+#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */
+
+
+
+
+
+/* 7.18.4  Macros for integer constants */
+
+#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS)
+
+
+
+/* 7.18.4.1  Macros for minimum-width integer constants
+
+
+
+    Accoding to Douglas Gwyn <gwyn at arl.mil>:
+
+	"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
+
+	9899:1999 as initially published, the expansion was required
+
+	to be an integer constant of precisely matching type, which
+
+	is impossible to accomplish for the shorter types on most
+
+	platforms, because C99 provides no standard way to designate
+
+	an integer constant with width less than that of type int.
+
+	TC1 changed this to require just an integer constant
+
+	*expression* with *promoted* type."
+
+*/
+
+
+
+#define INT8_C(val) ((int8_t) + (val))
+
+#define UINT8_C(val) ((uint8_t) + (val##U))
+
+#define INT16_C(val) ((int16_t) + (val))
+
+#define UINT16_C(val) ((uint16_t) + (val##U))
+
+
+
+#define INT32_C(val) val##L
+
+#define UINT32_C(val) val##UL
+
+#define INT64_C(val) val##LL
+
+#define UINT64_C(val) val##ULL
+
+
+
+/* 7.18.4.2  Macros for greatest-width integer constants */
+
+#define INTMAX_C(val)  INT64_C(val)
+
+#define UINTMAX_C(val) UINT64_C(val)
+
+
+
+#endif  /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */
+
+
+
+#endif
+
+
+


More information about the Spice-commits mailing list