[Spice-devel] [PATCH spice 1/3] dcc: Rewrite dcc_image_compress

Pavel Grunt pgrunt at redhat.com
Mon Feb 15 12:57:57 UTC 2016


Rules are now:

Compression type:
  off      -> uncompressed
  quic     -> jpeg if possible else quic else off
  lz       -> lz if possible else off
  glz      -> glz if possible else lz else off
  auto_lz  -> lz if possible else jpeg else quic else off
  auto_glz -> glz if possible else lz else jpeg else quic else off
  lz4      -> lz4 if possible else lz else off
---
 server/dcc.c | 210 +++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 118 insertions(+), 92 deletions(-)

diff --git a/server/dcc.c b/server/dcc.c
index 9a4e90c..c479091 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -1080,124 +1080,150 @@ static int dcc_compress_image_quic(DisplayChannelClient *dcc, SpiceImage *dest,
     return TRUE;
 }
 
-#define MIN_SIZE_TO_COMPRESS 54
 #define MIN_DIMENSION_TO_QUIC 3
+/**
+ * quic doesn't handle:
+ *       (1) palette
+ */
+static bool can_quic_compress(SpiceBitmap *bitmap)
+{
+    return !bitmap_fmt_is_plt(bitmap->format) &&
+            bitmap->x >= MIN_DIMENSION_TO_QUIC && bitmap->y >= MIN_DIMENSION_TO_QUIC;
+}
+/**
+ * lz doesn't handle:
+ *       (1) bitmaps with strides that are larger than the width of the image in bytes
+ *       (2) unstable bitmaps
+ */
+static bool can_lz_compress(SpiceBitmap *bitmap)
+{
+    return !bitmap_has_extra_stride(bitmap) &&
+           !(bitmap->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE);
+}
+
+#define MIN_SIZE_TO_COMPRESS 54
+static SpiceImageCompression get_compression_for_bitmap(SpiceBitmap *bitmap,
+                                                        SpiceImageCompression preferred_compression,
+                                                        Drawable *drawable)
+{
+    if (bitmap->y * bitmap->stride < MIN_SIZE_TO_COMPRESS) { // TODO: change the size cond
+        return SPICE_IMAGE_COMPRESSION_OFF;
+    }
+    if (preferred_compression == SPICE_IMAGE_COMPRESSION_OFF) {
+        return SPICE_IMAGE_COMPRESSION_OFF;
+    }
+    if (preferred_compression == SPICE_IMAGE_COMPRESSION_QUIC) {
+        if (can_quic_compress(bitmap)) {
+            return SPICE_IMAGE_COMPRESSION_QUIC;
+        }
+        return SPICE_IMAGE_COMPRESSION_OFF;
+    }
+
+    if (preferred_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ ||
+        preferred_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) {
+        if (can_quic_compress(bitmap)) {
+            if (drawable == NULL ||
+                drawable->copy_bitmap_graduality == BITMAP_GRADUAL_INVALID) {
+                if (bitmap_fmt_has_graduality(bitmap->format) &&
+                    bitmap_get_graduality_level(bitmap) == BITMAP_GRADUAL_HIGH) {
+                    return SPICE_IMAGE_COMPRESSION_QUIC;
+                }
+            } else if (!can_lz_compress(bitmap) ||
+                       drawable->copy_bitmap_graduality == BITMAP_GRADUAL_HIGH) {
+                return SPICE_IMAGE_COMPRESSION_QUIC;
+            }
+        }
+        if (preferred_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) {
+            preferred_compression = SPICE_IMAGE_COMPRESSION_LZ;
+        } else {
+            preferred_compression = SPICE_IMAGE_COMPRESSION_GLZ;
+        }
+    }
+
+    if (preferred_compression == SPICE_IMAGE_COMPRESSION_GLZ) {
+        if (drawable == NULL || bitmap_fmt_has_graduality(bitmap->format)) {
+            preferred_compression = SPICE_IMAGE_COMPRESSION_LZ;
+        }
+    }
+
+    if (preferred_compression == SPICE_IMAGE_COMPRESSION_LZ4) {
+        if (!bitmap_fmt_is_rgb(bitmap->format)) {
+            preferred_compression = SPICE_IMAGE_COMPRESSION_LZ;
+        }
+    }
+
+    if (preferred_compression == SPICE_IMAGE_COMPRESSION_LZ ||
+        preferred_compression == SPICE_IMAGE_COMPRESSION_LZ4 ||
+        preferred_compression == SPICE_IMAGE_COMPRESSION_GLZ) {
+        if (can_lz_compress(bitmap)) {
+            return preferred_compression;
+        }
+        return SPICE_IMAGE_COMPRESSION_OFF;
+    }
+
+    return SPICE_IMAGE_COMPRESSION_INVALID;
+}
+
 int dcc_compress_image(DisplayChannelClient *dcc,
                        SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
                        int can_lossy,
                        compress_send_data_t* o_comp_data)
 {
     DisplayChannel *display_channel = DCC_TO_DC(dcc);
-    SpiceImageCompression image_compression = dcc->image_compression;
-    int quic_compress = FALSE;
+    SpiceImageCompression image_compression;
 
-    if ((image_compression == SPICE_IMAGE_COMPRESSION_OFF) ||
-        ((src->y * src->stride) < MIN_SIZE_TO_COMPRESS)) { // TODO: change the size cond
+    image_compression = get_compression_for_bitmap(src, dcc->image_compression, drawable);
+    switch (image_compression) {
+    case SPICE_IMAGE_COMPRESSION_OFF:
         return FALSE;
-    } else if (image_compression == SPICE_IMAGE_COMPRESSION_QUIC) {
-        if (bitmap_fmt_is_plt(src->format)) {
-            return FALSE;
-        } else {
-            quic_compress = TRUE;
-        }
-    } else {
-        /*
-            lz doesn't handle (1) bitmaps with strides that are larger than the width
-            of the image in bytes (2) unstable bitmaps
-        */
-        if (bitmap_has_extra_stride(src) || (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) {
-            if ((image_compression == SPICE_IMAGE_COMPRESSION_LZ) ||
-                (image_compression == SPICE_IMAGE_COMPRESSION_GLZ) ||
-                (image_compression == SPICE_IMAGE_COMPRESSION_LZ4) ||
-                bitmap_fmt_is_plt(src->format)) {
-                return FALSE;
-            } else {
-                quic_compress = TRUE;
-            }
-        } else {
-            if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
-                (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ)) {
-                if ((src->x < MIN_DIMENSION_TO_QUIC) || (src->y < MIN_DIMENSION_TO_QUIC)) {
-                    quic_compress = FALSE;
-                } else {
-                    if (drawable == NULL ||
-                        drawable->copy_bitmap_graduality == BITMAP_GRADUAL_INVALID) {
-                        quic_compress = bitmap_fmt_has_graduality(src->format) &&
-                            bitmap_get_graduality_level(src) == BITMAP_GRADUAL_HIGH;
-                    } else {
-                        quic_compress = (drawable->copy_bitmap_graduality == BITMAP_GRADUAL_HIGH);
-                    }
-                }
-            } else {
-                quic_compress = FALSE;
-            }
+    case SPICE_IMAGE_COMPRESSION_QUIC:
+        if (can_lossy && display_channel->enable_jpeg &&
+            (src->format != SPICE_BITMAP_FMT_RGBA || !bitmap_has_extra_stride(src))) {
+#ifdef COMPRESS_DEBUG
+            spice_info("JPEG compress");
+#endif
+            return dcc_compress_image_jpeg(dcc, dest, src, o_comp_data);
         }
-    }
-
-    if (quic_compress) {
 #ifdef COMPRESS_DEBUG
         spice_info("QUIC compress");
 #endif
-        // if bitmaps is picture-like, compress it using jpeg
-        if (can_lossy && display_channel->enable_jpeg &&
-            ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
-            (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ))) {
-            // if we use lz for alpha, the stride can't be extra
-            if (src->format != SPICE_BITMAP_FMT_RGBA || !bitmap_has_extra_stride(src)) {
-                return dcc_compress_image_jpeg(dcc, dest, src, o_comp_data);
-            }
-        }
         return dcc_compress_image_quic(dcc, dest, src, o_comp_data);
-    } else {
-        int glz;
-        int ret;
-        if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) ||
-            (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) {
-            glz = drawable != NULL && bitmap_fmt_has_graduality(src->format) &&
-                  ((src->x * src->y) < glz_enc_dictionary_get_size(dcc->glz_dict->dict));
-        } else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
-                   (image_compression == SPICE_IMAGE_COMPRESSION_LZ) ||
-                   (image_compression == SPICE_IMAGE_COMPRESSION_LZ4)) {
-            glz = FALSE;
-        } else {
-            spice_error("invalid image compression type %u", image_compression);
-            return FALSE;
-        }
-
-        if (glz) {
+    case SPICE_IMAGE_COMPRESSION_GLZ:
+        if ((src->x * src->y) < glz_enc_dictionary_get_size(dcc->glz_dict->dict)) {
+            int ret, frozen;
             /* using the global dictionary only if it is not frozen */
             pthread_rwlock_rdlock(&dcc->glz_dict->encode_lock);
-            if (!dcc->glz_dict->migrate_freeze) {
-                ret = dcc_compress_image_glz(dcc,
-                                             dest, src,
-                                             drawable, o_comp_data);
-            } else {
-                glz = FALSE;
+            frozen = dcc->glz_dict->migrate_freeze;
+            if (!frozen) {
+#ifdef COMPRESS_DEBUG
+                spice_info("LZ global compress fmt=%d", src->format);
+#endif
+                ret = dcc_compress_image_glz(dcc, dest, src, drawable, o_comp_data);
             }
             pthread_rwlock_unlock(&dcc->glz_dict->encode_lock);
+            if (!frozen) {
+                return ret;
+            }
         }
-
-        if (!glz) {
 #ifdef USE_LZ4
-            if (image_compression == SPICE_IMAGE_COMPRESSION_LZ4 &&
-                bitmap_fmt_is_rgb(src->format) &&
-                red_channel_client_test_remote_cap(&dcc->common.base,
-                        SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
-                ret = dcc_compress_image_lz4(dcc, dest, src, o_comp_data);
-            } else
-#endif
-                ret = dcc_compress_image_lz(dcc, dest, src, o_comp_data);
+    case SPICE_IMAGE_COMPRESSION_LZ4:
+        if (red_channel_client_test_remote_cap(&dcc->common.base,
+                                               SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
 #ifdef COMPRESS_DEBUG
-            spice_info("LZ LOCAL compress");
+            spice_info("LZ4 compress");
 #endif
+            return dcc_compress_image_lz4(dcc, dest, src, o_comp_data);
         }
+#endif
+    case SPICE_IMAGE_COMPRESSION_LZ:
 #ifdef COMPRESS_DEBUG
-        else {
-            spice_info("LZ global compress fmt=%d", src->format);
-        }
+        spice_info("LZ LOCAL compress");
 #endif
-        return ret;
+        return dcc_compress_image_lz(dcc, dest, src, o_comp_data);
+    default:
+        spice_error("invalid image compression type %u", image_compression);
     }
+    return FALSE;
 }
 
 #define CLIENT_PALETTE_CACHE
-- 
2.5.0



More information about the Spice-devel mailing list