[Spice-commits] 5 commits - common/canvas_base.c common/quic.c common/quic_family_tmpl.c common/quic_rgb_tmpl.c common/quic_tmpl.c spice.proto

Marc-André Lureau elmarco at kemper.freedesktop.org
Thu Sep 12 04:49:44 PDT 2013


 common/canvas_base.c      |   43 +++++++++++++++++++++++++++++++++++++++++++
 common/quic.c             |   25 ++++++++++++++++++++++++-
 common/quic_family_tmpl.c |   26 +++++++++++---------------
 common/quic_rgb_tmpl.c    |    6 +++---
 common/quic_tmpl.c        |   16 ++++++++--------
 spice.proto               |    4 ++++
 6 files changed, 93 insertions(+), 27 deletions(-)

New commits:
commit 4857653686d3b4c8f96aebe5a96d3573ecc5d147
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Sun Sep 8 21:04:49 2013 +0200

    quic: precompute golomb codes
    
    We can avoid repetitive computation by using two precomputed array, of
    8k each.
    
    before:
         1.79%  lt-spicy-stats  libspice-client-glib-2.0.so.8.4.0  [.]
         golomb_code_len_8bpc
    
    after:
         0.79%  lt-spicy-stats  libspice-client-glib-2.0.so.8.4.0  [.]
         golomb_code_len_8bpc

diff --git a/common/quic.c b/common/quic.c
index 3e7c802..c9c3624 100644
--- a/common/quic.c
+++ b/common/quic.c
@@ -75,6 +75,9 @@ typedef struct QuicFamily {
     unsigned int notGRsuffixlen[MAXNUMCODES];    /* indexed by code number, contains suffix
                                                     length of the not-GR codeword */
 
+    unsigned int golomb_code_len[256][MAXNUMCODES];
+    unsigned int golomb_code[256][MAXNUMCODES];
+
     /* array for translating distribution U to L for depths up to 8 bpp,
     initialized by decorelateinit() */
     BYTE xlatU2L[256];
@@ -360,9 +363,22 @@ static void corelate_init(QuicFamily *family, int bpc)
     }
 }
 
+static void golomb_coding_slow(QuicFamily *family, const BYTE n, const unsigned int l,
+                               unsigned int * const codeword,
+                               unsigned int * const codewordlen)
+{
+    if (n < family->nGRcodewords[l]) {
+        (*codeword) = bitat[l] | (n & bppmask[l]);
+        (*codewordlen) = (n >> l) + l + 1;
+    } else {
+        (*codeword) = n - family->nGRcodewords[l];
+        (*codewordlen) = family->notGRcwlen[l];
+    }
+}
+
 static void family_init(QuicFamily *family, int bpc, int limit)
 {
-    int l;
+    int l, b;
 
     for (l = 0; l < bpc; l++) { /* fill arrays indexed by code number */
         int altprefixlen, altcodewords;
@@ -378,6 +394,13 @@ static void family_init(QuicFamily *family, int bpc, int limit)
         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 */
+
+        for (b = 0; b < 256; b++) {
+            unsigned int code, len;
+            golomb_coding_slow(family, b, l, &code, &len);
+            family->golomb_code[b][l] = code;
+            family->golomb_code_len[b][l] = len;
+        }
     }
 
     decorelate_init(family, bpc);
diff --git a/common/quic_family_tmpl.c b/common/quic_family_tmpl.c
index 287ff6d..12ef62f 100644
--- a/common/quic_family_tmpl.c
+++ b/common/quic_family_tmpl.c
@@ -34,26 +34,21 @@
 #define BPC 5
 #endif
 
+static inline unsigned int FNAME(golomb_code)(const BYTE n, const unsigned int l)
+{
+    return VNAME(family).golomb_code[n][l];
+}
 
-static unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l)
+static inline 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];
-    }
+    return VNAME(family).golomb_code_len[n][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];
-    }
+    *codeword = FNAME(golomb_code)(n, l);
+    *codewordlen = FNAME(golomb_code_len)(n, l);
 }
 
 static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned int bits,
@@ -76,6 +71,7 @@ static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned
 static void FNAME(update_model)(CommonState *state, s_bucket * const bucket,
                                 const BYTE curval)
 {
+    spice_static_assert(BPC >= 1);
     const unsigned int bpp = BPC;
     COUNTER * const pcounters = bucket->pcounters;
     unsigned int i;
commit 8db88d28543b2f147a9e5b4bf6b0e5b5eba1c1c9
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Sun Sep 8 21:03:25 2013 +0200

    quic: compile with constant bpp
    
    This simplifies a little bit function calling, and allows for compiler
    to potentially specialize and optimize a bit better each version.

diff --git a/common/quic_family_tmpl.c b/common/quic_family_tmpl.c
index cca2c05..287ff6d 100644
--- a/common/quic_family_tmpl.c
+++ b/common/quic_family_tmpl.c
@@ -74,13 +74,13 @@ static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned
 
 /* update the bucket using just encoded curval */
 static void FNAME(update_model)(CommonState *state, s_bucket * const bucket,
-                                const BYTE curval, unsigned int bpp)
+                                const BYTE curval)
 {
+    const unsigned int bpp = BPC;
     COUNTER * const pcounters = bucket->pcounters;
     unsigned int i;
     unsigned int bestcode;
     unsigned int bestcodelen;
-    //unsigned int bpp = encoder->bpp;
 
     /* update counters, find minimum */
 
diff --git a/common/quic_rgb_tmpl.c b/common/quic_rgb_tmpl.c
index 37c908c..19cc348 100644
--- a/common/quic_rgb_tmpl.c
+++ b/common/quic_rgb_tmpl.c
@@ -178,11 +178,11 @@
 
 #define UPDATE_MODEL(index)                                                                 \
     update_model(&encoder->rgb_state, find_bucket(channel_r, correlate_row_r[index - 1]),   \
-                correlate_row_r[index], bpc);                                               \
+                correlate_row_r[index]);                                               \
     update_model(&encoder->rgb_state, find_bucket(channel_g, correlate_row_g[index - 1]),   \
-                correlate_row_g[index], bpc);                                               \
+                correlate_row_g[index]);                                               \
     update_model(&encoder->rgb_state, find_bucket(channel_b, correlate_row_b[index - 1]),   \
-                correlate_row_b[index], bpc);
+                correlate_row_b[index]);
 
 
 #ifdef RLE_PRED_1
diff --git a/common/quic_tmpl.c b/common/quic_tmpl.c
index b625daf..75f2ff0 100644
--- a/common/quic_tmpl.c
+++ b/common/quic_tmpl.c
@@ -173,7 +173,7 @@ static void FNAME(compress_row0_seg)(Encoder *encoder, Channel *channel, int i,
         } else {
             channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
             update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]),
-                         decorelate_drow[i], bpc);
+                         decorelate_drow[i]);
         }
         stopidx = ++i + channel->state.waitcnt;
     } else {
@@ -191,7 +191,7 @@ static void FNAME(compress_row0_seg)(Encoder *encoder, Channel *channel, int i,
         }
 
         update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]),
-                     decorelate_drow[stopidx], bpc);
+                     decorelate_drow[stopidx]);
         stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
     }
 
@@ -272,7 +272,7 @@ static void FNAME(compress_row_seg)(Encoder *encoder, Channel *channel, int i,
         } else {
             channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
             update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]),
-                         decorelate_drow[0], bpc);
+                         decorelate_drow[0]);
         }
         stopidx = ++i + channel->state.waitcnt;
     } else {
@@ -295,7 +295,7 @@ static void FNAME(compress_row_seg)(Encoder *encoder, Channel *channel, int i,
             }
 
             update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]),
-                         decorelate_drow[stopidx], bpc);
+                         decorelate_drow[stopidx]);
             stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
         }
 
@@ -406,7 +406,7 @@ static void FNAME(uncompress_row0_seg)(Encoder *encoder, Channel *channel, int i
         } else {
             channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
             update_model(&channel->state, find_bucket(channel, correlate_row[-1]),
-                         correlate_row[0], bpc);
+                         correlate_row[0]);
         }
         stopidx = ++i + channel->state.waitcnt;
     } else {
@@ -426,7 +426,7 @@ static void FNAME(uncompress_row0_seg)(Encoder *encoder, Channel *channel, int i
             decode_eatbits(encoder, codewordlen);
         }
 
-        update_model(&channel->state, pbucket, correlate_row[stopidx], bpc);
+        update_model(&channel->state, pbucket, correlate_row[stopidx]);
 
         stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
     }
@@ -511,7 +511,7 @@ static void FNAME(uncompress_row_seg)(Encoder *encoder, Channel *channel,
         } else {
             channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
             update_model(&channel->state, find_bucket(channel, correlate_row[-1]),
-                         correlate_row[0], bpc);
+                         correlate_row[0]);
         }
         stopidx = ++i + channel->state.waitcnt;
     } else {
@@ -535,7 +535,7 @@ static void FNAME(uncompress_row_seg)(Encoder *encoder, Channel *channel,
                 decode_eatbits(encoder, codewordlen);
             }
 
-            update_model(&channel->state, pbucket, correlate_row[stopidx], bpc);
+            update_model(&channel->state, pbucket, correlate_row[stopidx]);
 
             stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
         }
commit a7b93bd43d113af16220f86cbf3cd451ab859d7e
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Sun Sep 8 02:53:33 2013 +0200

    canvas: use precomputed revers_bits
    
    Thos function shows up in some profiling results, it seems we can
    trivially replace it with a precomputed array of 256bytes.
    
    before:
         5.66%           691  lt-spicy-stats
    libspice-client-glib-2.0.so.8.4.0  [.] revers_bits
    
    after:
         0.53%            64  lt-spicy-stats
    libspice-client-glib-2.0.so.8.4.0  [.] revers_bits

diff --git a/common/canvas_base.c b/common/canvas_base.c
index 38a8497..2753fae 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -1329,6 +1329,8 @@ static pixman_image_t* canvas_get_image_from_self(SpiceCanvas *canvas,
     return surface;
 }
 
+
+#ifdef REVERS_BITS_SLOW
 static inline uint8_t revers_bits(uint8_t byte)
 {
     uint8_t ret = 0;
@@ -1341,6 +1343,47 @@ static inline uint8_t revers_bits(uint8_t byte)
     }
     return ret;
 }
+#else
+static inline uint8_t revers_bits(uint8_t byte)
+{
+    static const uint8_t revers[] = {
+        0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+        0x8, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+        0x4, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+        0xc, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+        0x2, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+        0xa, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+        0x6, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+        0xe, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+        0x1, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+        0x9, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+        0x5, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+        0xd, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+        0x3, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+        0xb, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+        0x7, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+        0xf, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+    };
+
+    return revers[byte];
+}
+#endif
 
 static pixman_image_t *canvas_get_bitmap_mask(CanvasBase *canvas, SpiceBitmap* bitmap, int invers)
 {
commit 6440a1e533c49f51e3e69f36c0218a6ec19d31ca
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Sep 10 23:10:29 2013 +0200

    proto: add fake last message in base channel
    
    Make it explicit that 100 is the last value of the base channel
    messages. This allows clients to use the generated enum value too.

diff --git a/spice.proto b/spice.proto
index 728178b..04e7ea4 100644
--- a/spice.proto
+++ b/spice.proto
@@ -166,6 +166,8 @@ channel BaseChannel {
 
     Data list; /* the msg body is SpiceSubMessageList */
 
+    Empty base_last = 100;
+
  client:
     message {
 	uint32 generation;
commit 4d8d2b612473ddd645572b23f7bf2658de0ec4f5
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Sep 10 12:30:57 2013 +0200

    proto: comment future surface flags usage

diff --git a/spice.proto b/spice.proto
index 5eede6b..728178b 100644
--- a/spice.proto
+++ b/spice.proto
@@ -425,6 +425,8 @@ flags8 string_flags {
 };
 
 flags32 surface_flags {
+    /* Adding flags requires some caps check, since old clients only
+       treat the value as an enum and not as a flag (flag == PRIMARY) */
     PRIMARY
 };
 


More information about the Spice-commits mailing list