[Spice-commits] 10 commits - server/Makefile.am server/red_channel.c server/red_channel.h server/red_dispatcher.c server/red_time.c server/red_time.h server/red_worker.c server/red_worker.h server/spice_bitmap_utils.c server/spice_bitmap_utils.h server/spice_image_cache.c server/spice_image_cache.h server/spice_server_utils.h
Alon Levy
alon at kemper.freedesktop.org
Wed Aug 14 03:24:55 PDT 2013
server/Makefile.am | 5
server/red_channel.c | 106 +++++++++
server/red_channel.h | 10
server/red_dispatcher.c | 4
server/red_time.c | 1
server/red_time.h | 15 +
server/red_worker.c | 511 +++-----------------------------------------
server/red_worker.h | 18 -
server/spice_bitmap_utils.c | 167 ++++++++++++++
server/spice_bitmap_utils.h | 8
server/spice_image_cache.c | 135 +++++++++++
server/spice_image_cache.h | 39 +++
server/spice_server_utils.h | 23 +
13 files changed, 548 insertions(+), 494 deletions(-)
New commits:
commit ee382109a6d59c3e6591d49f9e25a6314d0d5b5f
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 15:31:56 2013 +0300
server: split spice_image_cache from red_worker
diff --git a/server/Makefile.am b/server/Makefile.am
index feee2f1..815f65e 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -100,6 +100,8 @@ libspice_server_la_SOURCES = \
spice_bitmap_utils.h \
spice_bitmap_utils.c \
spice_server_utils.h \
+ spice_image_cache.h \
+ spice_image_cache.c \
$(NULL)
if SUPPORT_TUNNEL
diff --git a/server/red_worker.c b/server/red_worker.c
index df5d01c..7f1aeda 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -85,6 +85,7 @@
#include "spice_server_utils.h"
#include "red_time.h"
#include "spice_bitmap_utils.h"
+#include "spice_image_cache.h"
//#define COMPRESS_STAT
//#define DUMP_BITMAP
@@ -757,29 +758,6 @@ typedef struct CursorChannel {
#endif
} CursorChannel;
-typedef struct ImageCacheItem {
- RingItem lru_link;
- uint64_t id;
-#ifdef IMAGE_CACHE_AGE
- uint32_t age;
-#endif
- struct ImageCacheItem *next;
- pixman_image_t *image;
-} ImageCacheItem;
-
-#define IMAGE_CACHE_HASH_SIZE 1024
-
-typedef struct ImageCache {
- SpiceImageCache base;
- ImageCacheItem *hash_table[IMAGE_CACHE_HASH_SIZE];
- Ring lru;
-#ifdef IMAGE_CACHE_AGE
- uint32_t age;
-#else
- uint32_t num_items;
-#endif
-} ImageCache;
-
enum {
TREE_ITEM_TYPE_DRAWABLE,
TREE_ITEM_TYPE_CONTAINER,
@@ -4300,140 +4278,6 @@ static void image_surface_init(RedWorker *worker)
worker->image_surfaces.ops = &image_surfaces_ops;
}
-static ImageCacheItem *image_cache_find(ImageCache *cache, uint64_t id)
-{
- ImageCacheItem *item = cache->hash_table[id % IMAGE_CACHE_HASH_SIZE];
-
- while (item) {
- if (item->id == id) {
- return item;
- }
- item = item->next;
- }
- return NULL;
-}
-
-static int image_cache_hit(ImageCache *cache, uint64_t id)
-{
- ImageCacheItem *item;
- if (!(item = image_cache_find(cache, id))) {
- return FALSE;
- }
-#ifdef IMAGE_CACHE_AGE
- item->age = cache->age;
-#endif
- ring_remove(&item->lru_link);
- ring_add(&cache->lru, &item->lru_link);
- return TRUE;
-}
-
-static void image_cache_remove(ImageCache *cache, ImageCacheItem *item)
-{
- ImageCacheItem **now;
-
- now = &cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE];
- for (;;) {
- spice_assert(*now);
- if (*now == item) {
- *now = item->next;
- break;
- }
- now = &(*now)->next;
- }
- ring_remove(&item->lru_link);
- pixman_image_unref(item->image);
- free(item);
-#ifndef IMAGE_CACHE_AGE
- cache->num_items--;
-#endif
-}
-
-#define IMAGE_CACHE_MAX_ITEMS 2
-
-static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_image_t *image)
-{
- ImageCache *cache = (ImageCache *)spice_cache;
- ImageCacheItem *item;
-
-#ifndef IMAGE_CACHE_AGE
- if (cache->num_items == IMAGE_CACHE_MAX_ITEMS) {
- ImageCacheItem *tail = (ImageCacheItem *)ring_get_tail(&cache->lru);
- spice_assert(tail);
- image_cache_remove(cache, tail);
- }
-#endif
-
- item = spice_new(ImageCacheItem, 1);
- item->id = id;
-#ifdef IMAGE_CACHE_AGE
- item->age = cache->age;
-#else
- cache->num_items++;
-#endif
- item->image = pixman_image_ref(image);
- ring_item_init(&item->lru_link);
-
- item->next = cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE];
- cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE] = item;
-
- ring_add(&cache->lru, &item->lru_link);
-}
-
-static pixman_image_t *image_cache_get(SpiceImageCache *spice_cache, uint64_t id)
-{
- ImageCache *cache = (ImageCache *)spice_cache;
-
- ImageCacheItem *item = image_cache_find(cache, id);
- if (!item) {
- spice_error("not found");
- }
- return pixman_image_ref(item->image);
-}
-
-static void image_cache_init(ImageCache *cache)
-{
- static SpiceImageCacheOps image_cache_ops = {
- image_cache_put,
- image_cache_get,
- };
-
- cache->base.ops = &image_cache_ops;
- memset(cache->hash_table, 0, sizeof(cache->hash_table));
- ring_init(&cache->lru);
-#ifdef IMAGE_CACHE_AGE
- cache->age = 0;
-#else
- cache->num_items = 0;
-#endif
-}
-
-static void image_cache_reset(ImageCache *cache)
-{
- ImageCacheItem *item;
-
- while ((item = (ImageCacheItem *)ring_get_head(&cache->lru))) {
- image_cache_remove(cache, item);
- }
-#ifdef IMAGE_CACHE_AGE
- cache->age = 0;
-#endif
-}
-
-#define IMAGE_CACHE_DEPTH 4
-
-static void image_cache_aging(ImageCache *cache)
-{
-#ifdef IMAGE_CACHE_AGE
- ImageCacheItem *item;
-
- cache->age++;
- while ((item = (ImageCacheItem *)ring_get_tail(&cache->lru)) &&
- cache->age - item->age > IMAGE_CACHE_DEPTH) {
- image_cache_remove(cache, item);
- }
-#endif
-}
-
static void localize_bitmap(RedWorker *worker, SpiceImage **image_ptr, SpiceImage *image_store,
Drawable *drawable)
{
diff --git a/server/spice_image_cache.c b/server/spice_image_cache.c
new file mode 100644
index 0000000..291094c
--- /dev/null
+++ b/server/spice_image_cache.c
@@ -0,0 +1,135 @@
+#include "spice_image_cache.h"
+
+static ImageCacheItem *image_cache_find(ImageCache *cache, uint64_t id)
+{
+ ImageCacheItem *item = cache->hash_table[id % IMAGE_CACHE_HASH_SIZE];
+
+ while (item) {
+ if (item->id == id) {
+ return item;
+ }
+ item = item->next;
+ }
+ return NULL;
+}
+
+int image_cache_hit(ImageCache *cache, uint64_t id)
+{
+ ImageCacheItem *item;
+ if (!(item = image_cache_find(cache, id))) {
+ return FALSE;
+ }
+#ifdef IMAGE_CACHE_AGE
+ item->age = cache->age;
+#endif
+ ring_remove(&item->lru_link);
+ ring_add(&cache->lru, &item->lru_link);
+ return TRUE;
+}
+
+static void image_cache_remove(ImageCache *cache, ImageCacheItem *item)
+{
+ ImageCacheItem **now;
+
+ now = &cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE];
+ for (;;) {
+ spice_assert(*now);
+ if (*now == item) {
+ *now = item->next;
+ break;
+ }
+ now = &(*now)->next;
+ }
+ ring_remove(&item->lru_link);
+ pixman_image_unref(item->image);
+ free(item);
+#ifndef IMAGE_CACHE_AGE
+ cache->num_items--;
+#endif
+}
+
+#define IMAGE_CACHE_MAX_ITEMS 2
+
+static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_image_t *image)
+{
+ ImageCache *cache = (ImageCache *)spice_cache;
+ ImageCacheItem *item;
+
+#ifndef IMAGE_CACHE_AGE
+ if (cache->num_items == IMAGE_CACHE_MAX_ITEMS) {
+ ImageCacheItem *tail = (ImageCacheItem *)ring_get_tail(&cache->lru);
+ spice_assert(tail);
+ image_cache_remove(cache, tail);
+ }
+#endif
+
+ item = spice_new(ImageCacheItem, 1);
+ item->id = id;
+#ifdef IMAGE_CACHE_AGE
+ item->age = cache->age;
+#else
+ cache->num_items++;
+#endif
+ item->image = pixman_image_ref(image);
+ ring_item_init(&item->lru_link);
+
+ item->next = cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE];
+ cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE] = item;
+
+ ring_add(&cache->lru, &item->lru_link);
+}
+
+static pixman_image_t *image_cache_get(SpiceImageCache *spice_cache, uint64_t id)
+{
+ ImageCache *cache = (ImageCache *)spice_cache;
+
+ ImageCacheItem *item = image_cache_find(cache, id);
+ if (!item) {
+ spice_error("not found");
+ }
+ return pixman_image_ref(item->image);
+}
+
+void image_cache_init(ImageCache *cache)
+{
+ static SpiceImageCacheOps image_cache_ops = {
+ image_cache_put,
+ image_cache_get,
+ };
+
+ cache->base.ops = &image_cache_ops;
+ memset(cache->hash_table, 0, sizeof(cache->hash_table));
+ ring_init(&cache->lru);
+#ifdef IMAGE_CACHE_AGE
+ cache->age = 0;
+#else
+ cache->num_items = 0;
+#endif
+}
+
+void image_cache_reset(ImageCache *cache)
+{
+ ImageCacheItem *item;
+
+ while ((item = (ImageCacheItem *)ring_get_head(&cache->lru))) {
+ image_cache_remove(cache, item);
+ }
+#ifdef IMAGE_CACHE_AGE
+ cache->age = 0;
+#endif
+}
+
+#define IMAGE_CACHE_DEPTH 4
+
+void image_cache_aging(ImageCache *cache)
+{
+#ifdef IMAGE_CACHE_AGE
+ ImageCacheItem *item;
+
+ cache->age++;
+ while ((item = (ImageCacheItem *)ring_get_tail(&cache->lru)) &&
+ cache->age - item->age > IMAGE_CACHE_DEPTH) {
+ image_cache_remove(cache, item);
+ }
+#endif
+}
diff --git a/server/spice_image_cache.h b/server/spice_image_cache.h
new file mode 100644
index 0000000..f11cebc
--- /dev/null
+++ b/server/spice_image_cache.h
@@ -0,0 +1,39 @@
+#ifndef H_SPICE_IMAGE_CACHE
+#define H_SPICE_IMAGE_CACHE
+
+#include <inttypes.h>
+
+#include "common/pixman_utils.h"
+#include "common/canvas_base.h"
+
+#include "common/ring.h"
+
+typedef struct ImageCacheItem {
+ RingItem lru_link;
+ uint64_t id;
+#ifdef IMAGE_CACHE_AGE
+ uint32_t age;
+#endif
+ struct ImageCacheItem *next;
+ pixman_image_t *image;
+} ImageCacheItem;
+
+#define IMAGE_CACHE_HASH_SIZE 1024
+
+typedef struct ImageCache {
+ SpiceImageCache base;
+ ImageCacheItem *hash_table[IMAGE_CACHE_HASH_SIZE];
+ Ring lru;
+#ifdef IMAGE_CACHE_AGE
+ uint32_t age;
+#else
+ uint32_t num_items;
+#endif
+} ImageCache;
+
+int image_cache_hit(ImageCache *cache, uint64_t id);
+void image_cache_init(ImageCache *cache);
+void image_cache_reset(ImageCache *cache);
+void image_cache_aging(ImageCache *cache);
+
+#endif
commit 1bbce9ba05a63e50a4762b3adad773bb656b2c64
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 15:22:29 2013 +0300
server/red_worker: s/image_cache_eaging/image_cache_aging/
diff --git a/server/red_worker.c b/server/red_worker.c
index 1caaa51..df5d01c 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -4421,7 +4421,7 @@ static void image_cache_reset(ImageCache *cache)
#define IMAGE_CACHE_DEPTH 4
-static void image_cache_eaging(ImageCache *cache)
+static void image_cache_aging(ImageCache *cache)
{
#ifdef IMAGE_CACHE_AGE
ImageCacheItem *item;
@@ -4500,7 +4500,7 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable)
surface = &worker->surfaces[drawable->surface_id];
canvas = surface->context.canvas;
- image_cache_eaging(&worker->image_cache);
+ image_cache_aging(&worker->image_cache);
worker->preload_group_id = drawable->group_id;
commit 7241cc9544de818eb07de7dd99d72f8451ed8038
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 15:20:38 2013 +0300
server: move surface_format_to_image_type to spice_bitmap_utils
diff --git a/server/red_worker.c b/server/red_worker.c
index 175cf92..1caaa51 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -84,6 +84,7 @@
#include "main_dispatcher.h"
#include "spice_server_utils.h"
#include "red_time.h"
+#include "spice_bitmap_utils.h"
//#define COMPRESS_STAT
//#define DUMP_BITMAP
@@ -95,10 +96,6 @@
//#define ACYCLIC_SURFACE_DEBUG
//#define DEBUG_CURSORS
-#ifdef DUMP_BITMAP
-#include "spice_bitmap_utils.h"
-#endif
-
//#define UPDATE_AREA_BY_TREE
#define CMD_RING_POLL_TIMEOUT 10 //milli
@@ -3931,23 +3928,6 @@ static void red_get_area(RedWorker *worker, int surface_id, const SpiceRect *are
canvas->ops->read_bits(canvas, dest, dest_stride, area);
}
-static int surface_format_to_image_type(uint32_t surface_format)
-{
- switch (surface_format) {
- case SPICE_SURFACE_FMT_16_555:
- return SPICE_BITMAP_FMT_16BIT;
- case SPICE_SURFACE_FMT_32_xRGB:
- return SPICE_BITMAP_FMT_32BIT;
- case SPICE_SURFACE_FMT_32_ARGB:
- return SPICE_BITMAP_FMT_RGBA;
- case SPICE_SURFACE_FMT_8_A:
- return SPICE_BITMAP_FMT_8BIT_A;
- default:
- spice_critical("Unsupported surface format");
- }
- return 0;
-}
-
static int rgb32_data_has_alpha(int width, int height, size_t stride,
uint8_t *data, int *all_set_out)
{
@@ -4008,7 +3988,7 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_RED, ++worker->bits_unique);
image->u.bitmap.flags = surface->context.top_down ? SPICE_BITMAP_FLAGS_TOP_DOWN : 0;
- image->u.bitmap.format = surface_format_to_image_type(surface->context.format);
+ image->u.bitmap.format = spice_bitmap_from_surface_type(surface->context.format);
image->u.bitmap.stride = dest_stride;
image->descriptor.width = image->u.bitmap.x = width;
image->descriptor.height = image->u.bitmap.y = height;
@@ -5309,7 +5289,7 @@ static ImageItem *red_add_surface_area_image(DisplayChannelClient *dcc, int surf
item->refs = 1;
item->surface_id = surface_id;
item->image_format =
- surface_format_to_image_type(surface->context.format);
+ spice_bitmap_from_surface_type(surface->context.format);
item->image_flags = 0;
item->pos.x = area->left;
item->pos.y = area->top;
@@ -9767,7 +9747,7 @@ static inline void flush_cursor_commands(RedWorker *worker)
}
}
-// TODO: on timeout, don't disconnect all channeld immeduiatly - try to disconnect the slowest ones
+// TODO: on timeout, don't disconnect all channels immediatly - try to disconnect the slowest ones
// first and maybe turn timeouts to several timeouts in order to disconnect channels gradually.
// Should use disconnect or shutdown?
static inline void flush_all_qxl_commands(RedWorker *worker)
diff --git a/server/spice_bitmap_utils.c b/server/spice_bitmap_utils.c
index 9044622..ce0a5ed 100644
--- a/server/spice_bitmap_utils.c
+++ b/server/spice_bitmap_utils.c
@@ -5,6 +5,23 @@
#include "spice_bitmap_utils.h"
+int spice_bitmap_from_surface_type(uint32_t surface_format)
+{
+ switch (surface_format) {
+ case SPICE_SURFACE_FMT_16_555:
+ return SPICE_BITMAP_FMT_16BIT;
+ case SPICE_SURFACE_FMT_32_xRGB:
+ return SPICE_BITMAP_FMT_32BIT;
+ case SPICE_SURFACE_FMT_32_ARGB:
+ return SPICE_BITMAP_FMT_RGBA;
+ case SPICE_SURFACE_FMT_8_A:
+ return SPICE_BITMAP_FMT_8BIT_A;
+ default:
+ spice_critical("Unsupported surface format");
+ }
+ return 0;
+}
+
#define RAM_PATH "/tmp/tmpfs"
static void dump_palette(FILE *f, SpicePalette* plt)
diff --git a/server/spice_bitmap_utils.h b/server/spice_bitmap_utils.h
index ae4939f..69860e5 100644
--- a/server/spice_bitmap_utils.h
+++ b/server/spice_bitmap_utils.h
@@ -3,4 +3,6 @@
void dump_bitmap(SpiceBitmap *bitmap);
+int spice_bitmap_from_surface_type(uint32_t surface_format);
+
#endif
commit 9b8ff0428468b7f081fe6f2b27774af2d0b4dadf
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 19:48:24 2013 +0300
server: s/red_wait_all_sent/red_channel_wait_all_sent/
diff --git a/server/red_channel.c b/server/red_channel.c
index d0b979e..37b0c1c 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -2274,7 +2274,7 @@ static void rcc_shutdown_if_pending_send(RedChannelClient *rcc)
}
}
-void red_wait_all_sent(RedChannel *channel)
+void red_channel_wait_all_sent(RedChannel *channel)
{
uint64_t end_time;
uint32_t max_pipe_size;
diff --git a/server/red_channel.h b/server/red_channel.h
index b2a3a6a..9021b3f 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -604,6 +604,6 @@ void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
void red_wait_outgoing_item(RedChannelClient *rcc);
/* blocking function */
-void red_wait_all_sent(RedChannel *channel);
+void red_channel_wait_all_sent(RedChannel *channel);
#endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 0e86cff..175cf92 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -11136,7 +11136,7 @@ static inline void red_cursor_reset(RedWorker *worker)
if (!worker->cursor_channel->common.during_target_migrate) {
red_pipes_add_verb(&worker->cursor_channel->common.base, SPICE_MSG_CURSOR_RESET);
}
- red_wait_all_sent(&worker->cursor_channel->common.base);
+ red_channel_wait_all_sent(&worker->cursor_channel->common.base);
}
}
@@ -11419,8 +11419,8 @@ void handle_dev_stop(void *opaque, void *payload)
* purge the pipe, send destroy_all_surfaces
* to the client (there is no such message right now), and start
* from scratch on the destination side */
- red_wait_all_sent(&worker->display_channel->common.base);
- red_wait_all_sent(&worker->cursor_channel->common.base);
+ red_channel_wait_all_sent(&worker->display_channel->common.base);
+ red_channel_wait_all_sent(&worker->cursor_channel->common.base);
}
static int display_channel_wait_for_migrate_data(DisplayChannel *display)
commit bc50ff07676fa0b15df3aa2ae7e54936a8f81f95
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 15:01:42 2013 +0300
server: move three functions to red_channel
Three blocking functions, one was split to leave the display channel
specific referencing of the DrawablePipeItem being sent inside
red_worker, but the rest (most) of the timeout logic was moved to
red_channel, including the associated constants.
Moved functions:
red_channel_client_wait_pipe_item_sent
red_wait_outgoing_item
red_wait_all_sent
Introduces red_time.h & red_time.c for a small helper function dealing
with time.h
diff --git a/server/red_channel.c b/server/red_channel.c
index d565634..d0b979e 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -41,6 +41,7 @@
#include "red_channel.h"
#include "reds.h"
#include "main_dispatcher.h"
+#include "red_time.h"
typedef struct EmptyMsgPipeItem {
PipeItem base;
@@ -50,6 +51,12 @@ typedef struct EmptyMsgPipeItem {
#define PING_TEST_TIMEOUT_MS 15000
#define PING_TEST_IDLE_NET_TIMEOUT_MS 100
+#define DETACH_TIMEOUT 15000000000ULL //nano
+#define DETACH_SLEEP_DURATION 10000 //micro
+
+#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano
+#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro
+
enum QosPingState {
PING_STATE_NONE,
PING_STATE_TIMER,
@@ -2195,3 +2202,102 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel)
}
return sum;
}
+
+void red_wait_outgoing_item(RedChannelClient *rcc)
+{
+ uint64_t end_time;
+ int blocked;
+
+ if (!red_channel_client_blocked(rcc)) {
+ return;
+ }
+ end_time = red_now() + DETACH_TIMEOUT;
+ spice_info("blocked");
+
+ do {
+ usleep(DETACH_SLEEP_DURATION);
+ red_channel_client_receive(rcc);
+ red_channel_client_send(rcc);
+ } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time);
+
+ if (blocked) {
+ spice_warning("timeout");
+ // TODO - shutting down the socket but we still need to trigger
+ // disconnection. Right now we wait for main channel to error for that.
+ red_channel_client_shutdown(rcc);
+ } else {
+ spice_assert(red_channel_client_no_item_being_sent(rcc));
+ }
+}
+
+/* TODO: more evil sync stuff. anything with the word wait in it's name. */
+void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
+ PipeItem *item)
+{
+ uint64_t end_time;
+ int item_in_pipe;
+
+ spice_info(NULL);
+
+ end_time = red_now() + CHANNEL_PUSH_TIMEOUT;
+
+ rcc->channel->channel_cbs.hold_item(rcc, item);
+
+ if (red_channel_client_blocked(rcc)) {
+ red_channel_client_receive(rcc);
+ red_channel_client_send(rcc);
+ }
+ red_channel_client_push(rcc);
+
+ while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) {
+ usleep(CHANNEL_PUSH_SLEEP_DURATION);
+ red_channel_client_receive(rcc);
+ red_channel_client_send(rcc);
+ red_channel_client_push(rcc);
+ }
+
+ if (item_in_pipe) {
+ spice_warning("timeout");
+ red_channel_client_disconnect(rcc);
+ } else {
+ red_wait_outgoing_item(rcc);
+ }
+ red_channel_client_release_item(rcc, item, TRUE);
+}
+
+static void rcc_shutdown_if_pending_send(RedChannelClient *rcc)
+{
+ if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) {
+ red_channel_client_shutdown(rcc);
+ } else {
+ spice_assert(red_channel_client_no_item_being_sent(rcc));
+ }
+}
+
+void red_wait_all_sent(RedChannel *channel)
+{
+ uint64_t end_time;
+ uint32_t max_pipe_size;
+ int blocked = FALSE;
+
+ end_time = red_now() + DETACH_TIMEOUT;
+
+ red_channel_push(channel);
+ while (((max_pipe_size = red_channel_max_pipe_size(channel)) ||
+ (blocked = red_channel_any_blocked(channel))) &&
+ red_now() < end_time) {
+ spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked);
+ usleep(DETACH_SLEEP_DURATION);
+ red_channel_receive(channel);
+ red_channel_send(channel);
+ red_channel_push(channel);
+ }
+
+ if (max_pipe_size || blocked) {
+ spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)",
+ max_pipe_size, blocked);
+ red_channel_apply_clients(channel, rcc_shutdown_if_pending_send);
+ } else {
+ spice_assert(red_channel_no_item_being_sent(channel));
+ }
+}
diff --git a/server/red_channel.h b/server/red_channel.h
index 0dd73ea..b2a3a6a 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -596,4 +596,14 @@ int red_client_during_migrate_at_target(RedClient *client);
void red_client_migrate(RedClient *client);
+/* blocking function */
+void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
+ PipeItem *item);
+
+/* blocking function */
+void red_wait_outgoing_item(RedChannelClient *rcc);
+
+/* blocking function */
+void red_wait_all_sent(RedChannel *channel);
+
#endif
diff --git a/server/red_time.c b/server/red_time.c
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/server/red_time.c
@@ -0,0 +1 @@
+
diff --git a/server/red_time.h b/server/red_time.h
new file mode 100644
index 0000000..ffa97f2
--- /dev/null
+++ b/server/red_time.h
@@ -0,0 +1,15 @@
+#ifndef H_RED_TIME
+#define H_RED_TIME
+
+#include <time.h>
+
+static inline uint64_t red_now(void)
+{
+ struct timespec time;
+
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ return ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
+}
+
+#endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 3b9c5b0..0e86cff 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -83,6 +83,7 @@
#include "spice_timer_queue.h"
#include "main_dispatcher.h"
#include "spice_server_utils.h"
+#include "red_time.h"
//#define COMPRESS_STAT
//#define DUMP_BITMAP
@@ -103,12 +104,6 @@
#define CMD_RING_POLL_TIMEOUT 10 //milli
#define CMD_RING_POLL_RETRIES 200
-#define DETACH_TIMEOUT 15000000000ULL //nano
-#define DETACH_SLEEP_DURATION 10000 //micro
-
-#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano
-#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro
-
#define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano
#define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec
#define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro
@@ -1104,10 +1099,8 @@ static void cursor_channel_client_release_item_before_push(CursorChannelClient *
PipeItem *item);
static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc,
PipeItem *item);
-static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item);
static void red_push_monitors_config(DisplayChannelClient *dcc);
-static inline uint64_t red_now(void);
/*
* Macros to make iterating over stuff easier
@@ -2095,12 +2088,10 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int
}
if (item) {
- red_wait_pipe_item_sent(&dcc->common.base, item);
+ red_channel_client_wait_pipe_item_sent(&dcc->common.base, item);
}
}
-static void red_wait_outgoing_item(RedChannelClient *rcc);
-
static void red_clear_surface_drawables_from_pipes(RedWorker *worker, int surface_id,
int force, int wait_for_outgoing_item)
{
@@ -5086,15 +5077,6 @@ static void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint
red_release_cursor(worker, cursor_item);
}
-static inline uint64_t red_now(void)
-{
- struct timespec time;
-
- clock_gettime(CLOCK_MONOTONIC, &time);
-
- return ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
-}
-
static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty)
{
QXLCommandExt ext_cmd;
@@ -10986,105 +10968,6 @@ typedef struct __attribute__ ((__packed__)) CursorData {
SpiceCursor _cursor;
} CursorData;
-static void red_wait_outgoing_item(RedChannelClient *rcc)
-{
- uint64_t end_time;
- int blocked;
-
- if (!red_channel_client_blocked(rcc)) {
- return;
- }
- end_time = red_now() + DETACH_TIMEOUT;
- spice_info("blocked");
-
- do {
- usleep(DETACH_SLEEP_DURATION);
- red_channel_client_receive(rcc);
- red_channel_client_send(rcc);
- } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time);
-
- if (blocked) {
- spice_warning("timeout");
- // TODO - shutting down the socket but we still need to trigger
- // disconnection. Right now we wait for main channel to error for that.
- red_channel_client_shutdown(rcc);
- } else {
- spice_assert(red_channel_client_no_item_being_sent(rcc));
- }
-}
-
-static void rcc_shutdown_if_pending_send(RedChannelClient *rcc)
-{
- if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) {
- red_channel_client_shutdown(rcc);
- } else {
- spice_assert(red_channel_client_no_item_being_sent(rcc));
- }
-}
-
-static void red_wait_all_sent(RedChannel *channel)
-{
- uint64_t end_time;
- uint32_t max_pipe_size;
- int blocked = FALSE;
-
- end_time = red_now() + DETACH_TIMEOUT;
-
- red_channel_push(channel);
- while (((max_pipe_size = red_channel_max_pipe_size(channel)) ||
- (blocked = red_channel_any_blocked(channel))) &&
- red_now() < end_time) {
- spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked);
- usleep(DETACH_SLEEP_DURATION);
- red_channel_receive(channel);
- red_channel_send(channel);
- red_channel_push(channel);
- }
-
- if (max_pipe_size || blocked) {
- spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)",
- max_pipe_size, blocked);
- red_channel_apply_clients(channel, rcc_shutdown_if_pending_send);
- } else {
- spice_assert(red_channel_no_item_being_sent(channel));
- }
-}
-
-/* TODO: more evil sync stuff. anything with the word wait in it's name. */
-static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item)
-{
- DrawablePipeItem *dpi;
- uint64_t end_time;
- int item_in_pipe;
-
- spice_info(NULL);
- dpi = SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item);
- ref_drawable_pipe_item(dpi);
-
- end_time = red_now() + CHANNEL_PUSH_TIMEOUT;
-
- if (red_channel_client_blocked(rcc)) {
- red_channel_client_receive(rcc);
- red_channel_client_send(rcc);
- }
- red_channel_client_push(rcc);
-
- while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) {
- usleep(CHANNEL_PUSH_SLEEP_DURATION);
- red_channel_client_receive(rcc);
- red_channel_client_send(rcc);
- red_channel_client_push(rcc);
- }
-
- if (item_in_pipe) {
- spice_warning("timeout");
- red_channel_client_disconnect(rcc);
- } else {
- red_wait_outgoing_item(rcc);
- }
- put_drawable_pipe_item(dpi);
-}
-
static void surface_dirty_region_to_rects(RedSurface *surface,
QXLRect *qxl_dirty_rects,
uint32_t num_dirty_rects,
commit fe38ddf724a7cd47fe8225ba6b10e9abaaf53c89
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 14:44:21 2013 +0300
server: move bit set/clear utilities out of red_worker.h
diff --git a/server/Makefile.am b/server/Makefile.am
index e5392ba..feee2f1 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -99,6 +99,7 @@ libspice_server_la_SOURCES = \
zlib_encoder.h \
spice_bitmap_utils.h \
spice_bitmap_utils.c \
+ spice_server_utils.h \
$(NULL)
if SUPPORT_TUNNEL
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index ef47c28..03a4c4a 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -39,8 +39,10 @@
#endif // USE_OPENGL
#include "reds.h"
#include "dispatcher.h"
-#include "red_dispatcher.h"
#include "red_parse_qxl.h"
+#include "spice_server_utils.h"
+
+#include "red_dispatcher.h"
static int num_active_workers = 0;
diff --git a/server/red_worker.c b/server/red_worker.c
index 0704279..3b9c5b0 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -82,6 +82,7 @@
#include "migration_protocol.h"
#include "spice_timer_queue.h"
#include "main_dispatcher.h"
+#include "spice_server_utils.h"
//#define COMPRESS_STAT
//#define DUMP_BITMAP
diff --git a/server/red_worker.h b/server/red_worker.h
index 796b090..272661f 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -22,24 +22,6 @@
#include <errno.h>
#include "red_common.h"
-
-static inline void set_bit(int index, uint32_t *addr)
-{
- uint32_t mask = 1 << index;
- __sync_or_and_fetch(addr, mask);
-}
-
-static inline void clear_bit(int index, uint32_t *addr)
-{
- uint32_t mask = ~(1 << index);
- __sync_and_and_fetch(addr, mask);
-}
-
-static inline int test_bit(int index, uint32_t val)
-{
- return val & (1u << index);
-}
-
enum {
RED_WORKER_PENDING_WAKEUP,
RED_WORKER_PENDING_OOM,
diff --git a/server/spice_server_utils.h b/server/spice_server_utils.h
new file mode 100644
index 0000000..b3ddc27
--- /dev/null
+++ b/server/spice_server_utils.h
@@ -0,0 +1,23 @@
+#ifndef H_SPICE_SERVER_UTIL
+#define H_SPICE_SERVER_UTIL
+
+#include <unistd.h>
+
+static inline void set_bit(int index, uint32_t *addr)
+{
+ uint32_t mask = 1 << index;
+ __sync_or_and_fetch(addr, mask);
+}
+
+static inline void clear_bit(int index, uint32_t *addr)
+{
+ uint32_t mask = ~(1 << index);
+ __sync_and_and_fetch(addr, mask);
+}
+
+static inline int test_bit(int index, uint32_t val)
+{
+ return val & (1u << index);
+}
+
+#endif
commit 376264b00925ce417be2a8a5097c26d7cc58d608
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 14:43:53 2013 +0300
server: move dump_bitmap to separate file
diff --git a/server/Makefile.am b/server/Makefile.am
index d351dae..e5392ba 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -97,6 +97,8 @@ libspice_server_la_SOURCES = \
spice_timer_queue.h \
zlib_encoder.c \
zlib_encoder.h \
+ spice_bitmap_utils.h \
+ spice_bitmap_utils.c \
$(NULL)
if SUPPORT_TUNNEL
diff --git a/server/red_worker.c b/server/red_worker.c
index 0674174..0704279 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -93,6 +93,10 @@
//#define ACYCLIC_SURFACE_DEBUG
//#define DEBUG_CURSORS
+#ifdef DUMP_BITMAP
+#include "spice_bitmap_utils.h"
+#endif
+
//#define UPDATE_AREA_BY_TREE
#define CMD_RING_POLL_TIMEOUT 10 //milli
@@ -1101,10 +1105,6 @@ static void cursor_channel_client_release_item_after_push(CursorChannelClient *c
PipeItem *item);
static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item);
-#ifdef DUMP_BITMAP
-static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id);
-#endif
-
static void red_push_monitors_config(DisplayChannelClient *dcc);
static inline uint64_t red_now(void);
@@ -12292,152 +12292,3 @@ SPICE_GNUC_NORETURN void *red_worker_main(void *arg)
}
abort();
}
-
-#ifdef DUMP_BITMAP
-#include <stdio.h>
-static void dump_palette(FILE *f, SpicePalette* plt)
-{
- int i;
- for (i = 0; i < plt->num_ents; i++) {
- fwrite(plt->ents + i, sizeof(uint32_t), 1, f);
- }
-}
-
-static void dump_line(FILE *f, uint8_t* line, uint16_t n_pixel_bits, int width, int row_size)
-{
- int i;
- int copy_bytes_size = SPICE_ALIGN(n_pixel_bits * width, 8) / 8;
-
- fwrite(line, 1, copy_bytes_size, f);
- if (row_size > copy_bytes_size) {
- // each line should be 4 bytes aligned
- for (i = copy_bytes_size; i < row_size; i++) {
- fprintf(f, "%c", 0);
- }
- }
-}
-
-#define RAM_PATH "/tmp/tmpfs"
-
-static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id)
-{
- static uint32_t file_id = 0;
-
- char file_str[200];
- int rgb = TRUE;
- uint16_t n_pixel_bits;
- SpicePalette *plt = NULL;
- uint32_t id;
- int row_size;
- uint32_t file_size;
- int alpha = 0;
- uint32_t header_size = 14 + 40;
- uint32_t bitmap_data_offset;
- uint32_t tmp_u32;
- int32_t tmp_32;
- uint16_t tmp_u16;
- FILE *f;
- int i;
-
- switch (bitmap->format) {
- case SPICE_BITMAP_FMT_1BIT_BE:
- case SPICE_BITMAP_FMT_1BIT_LE:
- rgb = FALSE;
- n_pixel_bits = 1;
- break;
- case SPICE_BITMAP_FMT_4BIT_BE:
- case SPICE_BITMAP_FMT_4BIT_LE:
- rgb = FALSE;
- n_pixel_bits = 4;
- break;
- case SPICE_BITMAP_FMT_8BIT:
- rgb = FALSE;
- n_pixel_bits = 8;
- break;
- case SPICE_BITMAP_FMT_16BIT:
- n_pixel_bits = 16;
- break;
- case SPICE_BITMAP_FMT_24BIT:
- n_pixel_bits = 24;
- break;
- case SPICE_BITMAP_FMT_32BIT:
- n_pixel_bits = 32;
- break;
- case SPICE_BITMAP_FMT_RGBA:
- n_pixel_bits = 32;
- alpha = 1;
- break;
- default:
- spice_error("invalid bitmap format %u", bitmap->format);
- }
-
- if (!rgb) {
- if (!bitmap->palette) {
- return; // dont dump masks.
- }
- plt = bitmap->palette;
- }
- row_size = (((bitmap->x * n_pixel_bits) + 31) / 32) * 4;
- bitmap_data_offset = header_size;
-
- if (plt) {
- bitmap_data_offset += plt->num_ents * 4;
- }
- file_size = bitmap_data_offset + (bitmap->y * row_size);
-
- id = ++file_id;
- sprintf(file_str, "%s/%u.bmp", RAM_PATH, id);
-
- f = fopen(file_str, "wb");
- if (!f) {
- spice_error("Error creating bmp");
- return;
- }
-
- /* writing the bmp v3 header */
- fprintf(f, "BM");
- fwrite(&file_size, sizeof(file_size), 1, f);
- tmp_u16 = alpha ? 1 : 0;
- fwrite(&tmp_u16, sizeof(tmp_u16), 1, f); // reserved for application
- tmp_u16 = 0;
- fwrite(&tmp_u16, sizeof(tmp_u16), 1, f);
- fwrite(&bitmap_data_offset, sizeof(bitmap_data_offset), 1, f);
- tmp_u32 = header_size - 14;
- fwrite(&tmp_u32, sizeof(tmp_u32), 1, f); // sub header size
- tmp_32 = bitmap->x;
- fwrite(&tmp_32, sizeof(tmp_32), 1, f);
- tmp_32 = bitmap->y;
- fwrite(&tmp_32, sizeof(tmp_32), 1, f);
-
- tmp_u16 = 1;
- fwrite(&tmp_u16, sizeof(tmp_u16), 1, f); // color plane
- fwrite(&n_pixel_bits, sizeof(n_pixel_bits), 1, f); // pixel depth
-
- tmp_u32 = 0;
- fwrite(&tmp_u32, sizeof(tmp_u32), 1, f); // compression method
-
- tmp_u32 = 0; //file_size - bitmap_data_offset;
- fwrite(&tmp_u32, sizeof(tmp_u32), 1, f); // image size
- tmp_32 = 0;
- fwrite(&tmp_32, sizeof(tmp_32), 1, f);
- fwrite(&tmp_32, sizeof(tmp_32), 1, f);
- tmp_u32 = (!plt) ? 0 : plt->num_ents; // plt entries
- fwrite(&tmp_u32, sizeof(tmp_u32), 1, f);
- tmp_u32 = 0;
- fwrite(&tmp_u32, sizeof(tmp_u32), 1, f);
-
- if (plt) {
- dump_palette(f, plt);
- }
- /* writing the data */
- for (i = 0; i < bitmap->data->num_chunks; i++) {
- SpiceChunk *chunk = &bitmap->data->chunk[i];
- int num_lines = chunk->len / bitmap->stride;
- for (i = 0; i < num_lines; i++) {
- dump_line(f, chunk->data + (i * bitmap->stride), n_pixel_bits, bitmap->x, row_size);
- }
- }
- fclose(f);
-}
-
-#endif
diff --git a/server/spice_bitmap_utils.c b/server/spice_bitmap_utils.c
new file mode 100644
index 0000000..9044622
--- /dev/null
+++ b/server/spice_bitmap_utils.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+
+#include "common/log.h"
+#include "common/draw.h"
+
+#include "spice_bitmap_utils.h"
+
+#define RAM_PATH "/tmp/tmpfs"
+
+static void dump_palette(FILE *f, SpicePalette* plt)
+{
+ int i;
+ for (i = 0; i < plt->num_ents; i++) {
+ fwrite(plt->ents + i, sizeof(uint32_t), 1, f);
+ }
+}
+
+static void dump_line(FILE *f, uint8_t* line, uint16_t n_pixel_bits, int width, int row_size)
+{
+ int i;
+ int copy_bytes_size = SPICE_ALIGN(n_pixel_bits * width, 8) / 8;
+
+ fwrite(line, 1, copy_bytes_size, f);
+ if (row_size > copy_bytes_size) {
+ // each line should be 4 bytes aligned
+ for (i = copy_bytes_size; i < row_size; i++) {
+ fprintf(f, "%c", 0);
+ }
+ }
+}
+void dump_bitmap(SpiceBitmap *bitmap)
+{
+ static uint32_t file_id = 0;
+
+ char file_str[200];
+ int rgb = TRUE;
+ uint16_t n_pixel_bits;
+ SpicePalette *plt = NULL;
+ uint32_t id;
+ int row_size;
+ uint32_t file_size;
+ int alpha = 0;
+ uint32_t header_size = 14 + 40;
+ uint32_t bitmap_data_offset;
+ uint32_t tmp_u32;
+ int32_t tmp_32;
+ uint16_t tmp_u16;
+ FILE *f;
+ int i;
+
+ switch (bitmap->format) {
+ case SPICE_BITMAP_FMT_1BIT_BE:
+ case SPICE_BITMAP_FMT_1BIT_LE:
+ rgb = FALSE;
+ n_pixel_bits = 1;
+ break;
+ case SPICE_BITMAP_FMT_4BIT_BE:
+ case SPICE_BITMAP_FMT_4BIT_LE:
+ rgb = FALSE;
+ n_pixel_bits = 4;
+ break;
+ case SPICE_BITMAP_FMT_8BIT:
+ rgb = FALSE;
+ n_pixel_bits = 8;
+ break;
+ case SPICE_BITMAP_FMT_16BIT:
+ n_pixel_bits = 16;
+ break;
+ case SPICE_BITMAP_FMT_24BIT:
+ n_pixel_bits = 24;
+ break;
+ case SPICE_BITMAP_FMT_32BIT:
+ n_pixel_bits = 32;
+ break;
+ case SPICE_BITMAP_FMT_RGBA:
+ n_pixel_bits = 32;
+ alpha = 1;
+ break;
+ default:
+ spice_error("invalid bitmap format %u", bitmap->format);
+ }
+
+ if (!rgb) {
+ if (!bitmap->palette) {
+ return; // dont dump masks.
+ }
+ plt = bitmap->palette;
+ }
+ row_size = (((bitmap->x * n_pixel_bits) + 31) / 32) * 4;
+ bitmap_data_offset = header_size;
+
+ if (plt) {
+ bitmap_data_offset += plt->num_ents * 4;
+ }
+ file_size = bitmap_data_offset + (bitmap->y * row_size);
+
+ id = ++file_id;
+ sprintf(file_str, "%s/%u.bmp", RAM_PATH, id);
+
+ f = fopen(file_str, "wb");
+ if (!f) {
+ spice_error("Error creating bmp");
+ return;
+ }
+
+ /* writing the bmp v3 header */
+ fprintf(f, "BM");
+ fwrite(&file_size, sizeof(file_size), 1, f);
+ tmp_u16 = alpha ? 1 : 0;
+ fwrite(&tmp_u16, sizeof(tmp_u16), 1, f); // reserved for application
+ tmp_u16 = 0;
+ fwrite(&tmp_u16, sizeof(tmp_u16), 1, f);
+ fwrite(&bitmap_data_offset, sizeof(bitmap_data_offset), 1, f);
+ tmp_u32 = header_size - 14;
+ fwrite(&tmp_u32, sizeof(tmp_u32), 1, f); // sub header size
+ tmp_32 = bitmap->x;
+ fwrite(&tmp_32, sizeof(tmp_32), 1, f);
+ tmp_32 = bitmap->y;
+ fwrite(&tmp_32, sizeof(tmp_32), 1, f);
+
+ tmp_u16 = 1;
+ fwrite(&tmp_u16, sizeof(tmp_u16), 1, f); // color plane
+ fwrite(&n_pixel_bits, sizeof(n_pixel_bits), 1, f); // pixel depth
+
+ tmp_u32 = 0;
+ fwrite(&tmp_u32, sizeof(tmp_u32), 1, f); // compression method
+
+ tmp_u32 = 0; //file_size - bitmap_data_offset;
+ fwrite(&tmp_u32, sizeof(tmp_u32), 1, f); // image size
+ tmp_32 = 0;
+ fwrite(&tmp_32, sizeof(tmp_32), 1, f);
+ fwrite(&tmp_32, sizeof(tmp_32), 1, f);
+ tmp_u32 = (!plt) ? 0 : plt->num_ents; // plt entries
+ fwrite(&tmp_u32, sizeof(tmp_u32), 1, f);
+ tmp_u32 = 0;
+ fwrite(&tmp_u32, sizeof(tmp_u32), 1, f);
+
+ if (plt) {
+ dump_palette(f, plt);
+ }
+ /* writing the data */
+ for (i = 0; i < bitmap->data->num_chunks; i++) {
+ SpiceChunk *chunk = &bitmap->data->chunk[i];
+ int num_lines = chunk->len / bitmap->stride;
+ for (i = 0; i < num_lines; i++) {
+ dump_line(f, chunk->data + (i * bitmap->stride), n_pixel_bits, bitmap->x, row_size);
+ }
+ }
+ fclose(f);
+}
diff --git a/server/spice_bitmap_utils.h b/server/spice_bitmap_utils.h
new file mode 100644
index 0000000..ae4939f
--- /dev/null
+++ b/server/spice_bitmap_utils.h
@@ -0,0 +1,6 @@
+#ifndef H_SPICE_BITMAP_UTILS
+#define H_SPICE_BITMAP_UTILS
+
+void dump_bitmap(SpiceBitmap *bitmap);
+
+#endif
commit ff672924caf10c055e827ece9459e1fe2372456c
Author: Alon Levy <alevy at redhat.com>
Date: Sat Aug 3 17:40:25 2013 +0200
server/red_worker.c:red_process_drawable: rename item to drawable
diff --git a/server/red_worker.c b/server/red_worker.c
index 29a6295..0674174 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -4189,23 +4189,23 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *red_draw
uint32_t group_id)
{
int surface_id;
- Drawable *item = get_drawable(worker, red_drawable->effect, red_drawable, group_id);
+ Drawable *drawable = get_drawable(worker, red_drawable->effect, red_drawable, group_id);
- if (!item) {
+ if (!drawable) {
rendering_incorrect("failed to get_drawable");
return;
}
- surface_id = item->surface_id;
+ surface_id = drawable->surface_id;
worker->surfaces[surface_id].refs++;
- region_add(&item->tree_item.base.rgn, &red_drawable->bbox);
+ region_add(&drawable->tree_item.base.rgn, &red_drawable->bbox);
#ifdef PIPE_DEBUG
printf("TEST: DRAWABLE: id %u type %s effect %u bbox %u %u %u %u\n",
- item->tree_item.base.id,
+ drawable->tree_item.base.id,
draw_type_to_str(red_drawable->type),
- item->tree_item.effect,
+ drawable->tree_item.effect,
red_drawable->bbox.top, red_drawable->bbox.left,
red_drawable->bbox.bottom, red_drawable->bbox.right);
#endif
@@ -4215,7 +4215,7 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *red_draw
region_init(&rgn);
add_clip_rects(&rgn, red_drawable->clip.rects);
- region_and(&item->tree_item.base.rgn, &rgn);
+ region_and(&drawable->tree_item.base.rgn, &rgn);
region_destroy(&rgn);
}
/*
@@ -4224,13 +4224,13 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *red_draw
However, surface->depend_on_me is affected by a drawable only
as long as it is in the current tree (hasn't been rendered yet).
*/
- red_inc_surfaces_drawable_dependencies(worker, item);
+ red_inc_surfaces_drawable_dependencies(worker, drawable);
- if (region_is_empty(&item->tree_item.base.rgn)) {
+ if (region_is_empty(&drawable->tree_item.base.rgn)) {
goto cleanup;
}
- if (!red_handle_self_bitmap(worker, item)) {
+ if (!red_handle_self_bitmap(worker, drawable)) {
goto cleanup;
}
@@ -4238,22 +4238,22 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *red_draw
goto cleanup;
}
- if (!red_handle_surfaces_dependencies(worker, item)) {
+ if (!red_handle_surfaces_dependencies(worker, drawable)) {
goto cleanup;
}
- if (red_current_add_qxl(worker, &worker->surfaces[surface_id].current, item,
+ if (red_current_add_qxl(worker, &worker->surfaces[surface_id].current, drawable,
red_drawable)) {
- if (item->tree_item.effect != QXL_EFFECT_OPAQUE) {
+ if (drawable->tree_item.effect != QXL_EFFECT_OPAQUE) {
worker->transparent_count++;
}
- red_pipes_add_drawable(worker, item);
+ red_pipes_add_drawable(worker, drawable);
#ifdef DRAW_ALL
- red_draw_qxl_drawable(worker, item);
+ red_draw_qxl_drawable(worker, drawable);
#endif
}
cleanup:
- release_drawable(worker, item);
+ release_drawable(worker, drawable);
}
static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uint32_t width,
commit 3a25c2070440dffbf34be16a02e1ad1b341de626
Author: Alon Levy <alevy at redhat.com>
Date: Sat Aug 3 17:39:39 2013 +0200
server/red_worker.c:red_process_drawable: rename drawable to red_drawable
diff --git a/server/red_worker.c b/server/red_worker.c
index 08e2a43..29a6295 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -4185,11 +4185,11 @@ static inline void red_inc_surfaces_drawable_dependencies(RedWorker *worker, Dra
}
}
-static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable,
+static inline void red_process_drawable(RedWorker *worker, RedDrawable *red_drawable,
uint32_t group_id)
{
int surface_id;
- Drawable *item = get_drawable(worker, drawable->effect, drawable, group_id);
+ Drawable *item = get_drawable(worker, red_drawable->effect, red_drawable, group_id);
if (!item) {
rendering_incorrect("failed to get_drawable");
@@ -4200,20 +4200,21 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable
worker->surfaces[surface_id].refs++;
- region_add(&item->tree_item.base.rgn, &drawable->bbox);
+ region_add(&item->tree_item.base.rgn, &red_drawable->bbox);
#ifdef PIPE_DEBUG
printf("TEST: DRAWABLE: id %u type %s effect %u bbox %u %u %u %u\n",
item->tree_item.base.id,
- draw_type_to_str(drawable->type),
+ draw_type_to_str(red_drawable->type),
item->tree_item.effect,
- drawable->bbox.top, drawable->bbox.left, drawable->bbox.bottom, drawable->bbox.right);
+ red_drawable->bbox.top, red_drawable->bbox.left,
+ red_drawable->bbox.bottom, red_drawable->bbox.right);
#endif
- if (drawable->clip.type == SPICE_CLIP_TYPE_RECTS) {
+ if (red_drawable->clip.type == SPICE_CLIP_TYPE_RECTS) {
QRegion rgn;
region_init(&rgn);
- add_clip_rects(&rgn, drawable->clip.rects);
+ add_clip_rects(&rgn, red_drawable->clip.rects);
region_and(&item->tree_item.base.rgn, &rgn);
region_destroy(&rgn);
}
@@ -4242,7 +4243,7 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable
}
if (red_current_add_qxl(worker, &worker->surfaces[surface_id].current, item,
- drawable)) {
+ red_drawable)) {
if (item->tree_item.effect != QXL_EFFECT_OPAQUE) {
worker->transparent_count++;
}
commit 478a1906b0e39b37a6cc8bc2e92161afe63bf57a
Author: Alon Levy <alevy at redhat.com>
Date: Mon Aug 12 12:45:56 2013 +0300
red_worker: mark DRAW_ALL as broken
setting DRAW_ALL define doesn't produce correct rendering. Using
update_area instead of red_draw_qxl_drawable will work but it shouldn't
be required. This is not work I intend to do right now, so marking it
for anyone looking at this in the future.
diff --git a/server/red_worker.c b/server/red_worker.c
index 9896696..08e2a43 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -87,6 +87,7 @@
//#define DUMP_BITMAP
//#define PIPE_DEBUG
//#define RED_WORKER_STAT
+/* TODO: DRAW_ALL is broken. */
//#define DRAW_ALL
//#define COMPRESS_DEBUG
//#define ACYCLIC_SURFACE_DEBUG
More information about the Spice-commits
mailing list