[Spice-devel] [PATCH spice v2 4/4] dcc: Rewrite dcc_image_compress

Pavel Grunt pgrunt at redhat.com
Fri Jan 15 08:11:35 PST 2016


Rules are now:

Compression type:
  off      -> uncompressed
  quic     -> quic if possible 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 | 170 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 84 insertions(+), 86 deletions(-)

diff --git a/server/dcc.c b/server/dcc.c
index 9b65031..8a0914d 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -1028,6 +1028,38 @@ static int dcc_compress_image_quic(DisplayChannelClient *dcc, SpiceImage *dest,
 }
 
 #define MIN_SIZE_TO_COMPRESS 54
+static bool can_compress_bitmap(SpiceBitmap *bitmap, SpiceImageCompression image_compression)
+{
+    spice_return_val_if_fail(image_compression > SPICE_IMAGE_COMPRESSION_INVALID &&
+                             image_compression < SPICE_IMAGE_COMPRESSION_ENUM_END, FALSE);
+
+   /*
+    quic doesn't handle:
+        (1) palette
+    lz doesn't handle:
+        (1) bitmaps with strides that are larger than the width of the image in bytes
+        (2) unstable bitmaps
+    */
+    if (bitmap->y * bitmap->stride < MIN_SIZE_TO_COMPRESS) { // TODO: change the size cond
+        return FALSE;
+    }
+    if (image_compression == SPICE_IMAGE_COMPRESSION_OFF) {
+        return FALSE;
+    }
+    if (image_compression == SPICE_IMAGE_COMPRESSION_QUIC) {
+        return !bitmap_fmt_is_plt(bitmap->format);
+    }
+    if (image_compression == SPICE_IMAGE_COMPRESSION_LZ ||
+        image_compression == SPICE_IMAGE_COMPRESSION_LZ4 ||
+        image_compression == SPICE_IMAGE_COMPRESSION_GLZ ||
+        bitmap_fmt_is_plt(bitmap->format)) {
+        return !bitmap_has_extra_stride(bitmap) &&
+               !(bitmap->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE);
+    }
+
+    return TRUE;
+}
+
 #define MIN_DIMENSION_TO_QUIC 3
 int dcc_compress_image(DisplayChannelClient *dcc,
                        SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
@@ -1037,49 +1069,29 @@ int dcc_compress_image(DisplayChannelClient *dcc,
     DisplayChannel *display_channel = DCC_TO_DC(dcc);
     SpiceImageCompression image_compression = dcc->image_compression;
     int quic_compress = FALSE;
+    int jpeg_compress = FALSE;
     uint32_t group_id;
 
-    if ((image_compression == SPICE_IMAGE_COMPRESSION_OFF) ||
-        ((src->y * src->stride) < MIN_SIZE_TO_COMPRESS)) { // TODO: change the size cond
+    if (!can_compress_bitmap(src, image_compression)) {
         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) &&
+    }
+    if (image_compression == SPICE_IMAGE_COMPRESSION_QUIC) {
+        quic_compress = TRUE;
+    } else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ ||
+               image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) &&
+               !bitmap_fmt_is_plt(src->format) &&
+               src->x >= MIN_DIMENSION_TO_QUIC && src->y >= MIN_DIMENSION_TO_QUIC) {
+        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;
-            }
+        } else {
+            quic_compress = bitmap_has_extra_stride(src) ||
+                            (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) ||
+                            drawable->copy_bitmap_graduality == BITMAP_GRADUAL_HIGH;
         }
+        jpeg_compress = can_lossy && display_channel->enable_jpeg &&
+                        (src->format != SPICE_BITMAP_FMT_RGBA || !bitmap_has_extra_stride(src));
     }
 
     if (drawable != NULL) {
@@ -1089,70 +1101,56 @@ int dcc_compress_image(DisplayChannelClient *dcc,
     }
 
     if (quic_compress) {
+        if (jpeg_compress) {
 #ifdef COMPRESS_DEBUG
-        spice_info("QUIC compress");
+            spice_info("JPEG 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, group_id);
-            }
+            /* bitmap is picture-like, compress it using jpeg */
+            return dcc_compress_image_jpeg(dcc, dest, src, o_comp_data, group_id);
         }
+#ifdef COMPRESS_DEBUG
+        spice_info("QUIC compress");
+#endif
         return dcc_compress_image_quic(dcc, dest, src, o_comp_data, group_id);
-    } else {
-        int glz;
-        int ret;
-        if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
-            (image_compression == SPICE_IMAGE_COMPRESSION_LZ) ||
-            (image_compression == SPICE_IMAGE_COMPRESSION_LZ4) ||
-            drawable == NULL) {
-            glz = FALSE;
-        } else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) ||
-                   (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) {
-            glz = bitmap_fmt_has_graduality(src->format) &&
-                  ((src->x * src->y) < glz_enc_dictionary_get_size(dcc->glz_dict->dict));
-        } else {
-            spice_error("invalid image compression type %u", image_compression);
-            return FALSE;
-        }
+    }
 
-        if (glz) {
+    if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) ||
+        (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) {
+        if (drawable != NULL &&
+            bitmap_fmt_has_graduality(src->format) &&
+            (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, group_id);
-            } else
-#endif
-                ret = dcc_compress_image_lz(dcc, dest, src, o_comp_data, group_id);
+    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)) {
 #ifdef COMPRESS_DEBUG
-            spice_info("LZ LOCAL compress");
+        spice_info("LZ4 compress");
 #endif
-        }
+        return dcc_compress_image_lz4(dcc, dest, src, o_comp_data, group_id);
+    }
+#endif
+
 #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, group_id);
 }
 
 #define CLIENT_PALETTE_CACHE
-- 
2.5.0



More information about the Spice-devel mailing list