From 372eb0072aca0051867b5b9496d5376c685567af Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 10 Sep 2013 22:59:31 +0200 Subject: tree: move that to a separate unit Acked-by: Frediano Ziglio --- server/Makefile.am | 2 + server/display-channel.h | 6 ++ server/red_worker.c | 265 ++--------------------------------------------- server/tree.c | 182 ++++++++++++++++++++++++++++++++ server/tree.h | 111 ++++++++++++++++++++ 5 files changed, 311 insertions(+), 255 deletions(-) create mode 100644 server/tree.c create mode 100644 server/tree.h diff --git a/server/Makefile.am b/server/Makefile.am index 87288ccb..c15a7014 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -130,6 +130,8 @@ libspice_server_la_SOURCES = \ spice_image_cache.c \ pixmap-cache.h \ pixmap-cache.c \ + tree.h \ + tree.c \ utils.h \ $(NULL) diff --git a/server/display-channel.h b/server/display-channel.h index e1ddc117..7f3ab7c2 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -18,9 +18,15 @@ #ifndef RED_WORKER_CLIENT_H_ # define RED_WORKER_CLIENT_H_ +#include + #include "red_worker.h" #include "cache-item.h" #include "pixmap-cache.h" +#include "reds_sw_canvas.h" +#include "glz_encoder_dictionary.h" +#include "glz_encoder.h" +#include "mjpeg_encoder.h" #include "utils.h" typedef struct Drawable Drawable; diff --git a/server/red_worker.c b/server/red_worker.c index 68cb153c..c1eff6d9 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -94,6 +94,7 @@ #include "pixmap-cache.h" #include "display-channel.h" #include "cursor-channel.h" +#include "tree.h" //#define COMPRESS_STAT //#define DUMP_BITMAP @@ -424,52 +425,6 @@ struct DisplayChannel { #endif }; -enum { - TREE_ITEM_TYPE_DRAWABLE, - TREE_ITEM_TYPE_CONTAINER, - TREE_ITEM_TYPE_SHADOW, -}; - -typedef struct TreeItem { - RingItem siblings_link; - uint32_t type; - struct Container *container; - QRegion rgn; -} TreeItem; - -#define IS_DRAW_ITEM(item) ((item)->type == TREE_ITEM_TYPE_DRAWABLE) - -typedef struct Shadow { - TreeItem base; - QRegion on_hold; - struct DrawItem* owner; -} Shadow; - -typedef struct Container { - TreeItem base; - Ring items; -} Container; - -typedef struct DrawItem { - TreeItem base; - uint8_t effect; - uint8_t container_root; - Shadow *shadow; -} DrawItem; - -typedef enum { - BITMAP_GRADUAL_INVALID, - BITMAP_GRADUAL_NOT_AVAIL, - BITMAP_GRADUAL_LOW, - BITMAP_GRADUAL_MEDIUM, - BITMAP_GRADUAL_HIGH, -} BitmapGradualType; - -typedef struct DependItem { - Drawable *drawable; - RingItem ring_item; -} DependItem; - typedef struct DrawablePipeItem { RingItem base; /* link for a list of pipe items held by Drawable */ PipeItem dpi_pipe_item; /* link for the client's pipe itself */ @@ -478,35 +433,6 @@ typedef struct DrawablePipeItem { uint8_t refs; } DrawablePipeItem; -struct Drawable { - uint8_t refs; - RingItem surface_list_link; - RingItem list_link; - DrawItem tree_item; - Ring pipes; - PipeItem *pipe_item_rest; - uint32_t size_pipe_item_rest; - RedDrawable *red_drawable; - - Ring glz_ring; - - red_time_t creation_time; - int frames_count; - int gradual_frames_count; - int last_gradual_frame; - Stream *stream; - Stream *sized_stream; - int streamable; - BitmapGradualType copy_bitmap_graduality; - uint32_t group_id; - DependItem depend_items[3]; - - int surface_id; - int surfaces_dest[3]; - - uint32_t process_commands_generation; -}; - typedef struct _Drawable _Drawable; struct _Drawable { union { @@ -927,91 +853,6 @@ static inline int validate_surface(RedWorker *worker, uint32_t surface_id) return 1; } -static const char *draw_type_to_str(uint8_t type) -{ - switch (type) { - case QXL_DRAW_FILL: - return "QXL_DRAW_FILL"; - case QXL_DRAW_OPAQUE: - return "QXL_DRAW_OPAQUE"; - case QXL_DRAW_COPY: - return "QXL_DRAW_COPY"; - case QXL_DRAW_TRANSPARENT: - return "QXL_DRAW_TRANSPARENT"; - case QXL_DRAW_ALPHA_BLEND: - return "QXL_DRAW_ALPHA_BLEND"; - case QXL_COPY_BITS: - return "QXL_COPY_BITS"; - case QXL_DRAW_BLEND: - return "QXL_DRAW_BLEND"; - case QXL_DRAW_BLACKNESS: - return "QXL_DRAW_BLACKNESS"; - case QXL_DRAW_WHITENESS: - return "QXL_DRAW_WHITENESS"; - case QXL_DRAW_INVERS: - return "QXL_DRAW_INVERS"; - case QXL_DRAW_ROP3: - return "QXL_DRAW_ROP3"; - case QXL_DRAW_COMPOSITE: - return "QXL_DRAW_COMPOSITE"; - case QXL_DRAW_STROKE: - return "QXL_DRAW_STROKE"; - case QXL_DRAW_TEXT: - return "QXL_DRAW_TEXT"; - default: - return "?"; - } -} - -static void show_red_drawable(RedWorker *worker, RedDrawable *drawable, const char *prefix) -{ - if (prefix) { - printf("%s: ", prefix); - } - - printf("%s effect %d bbox(%d %d %d %d)", - draw_type_to_str(drawable->type), - drawable->effect, - drawable->bbox.top, - drawable->bbox.left, - drawable->bbox.bottom, - drawable->bbox.right); - - switch (drawable->type) { - case QXL_DRAW_FILL: - case QXL_DRAW_OPAQUE: - case QXL_DRAW_COPY: - case QXL_DRAW_TRANSPARENT: - case QXL_DRAW_ALPHA_BLEND: - case QXL_COPY_BITS: - case QXL_DRAW_BLEND: - case QXL_DRAW_BLACKNESS: - case QXL_DRAW_WHITENESS: - case QXL_DRAW_INVERS: - case QXL_DRAW_ROP3: - case QXL_DRAW_COMPOSITE: - case QXL_DRAW_STROKE: - case QXL_DRAW_TEXT: - break; - default: - spice_error("bad drawable type"); - } - printf("\n"); -} - -static void show_draw_item(RedWorker *worker, DrawItem *draw_item, const char *prefix) -{ - if (prefix) { - printf("%s: ", prefix); - } - printf("effect %d bbox(%d %d %d %d)\n", - draw_item->effect, - draw_item->base.rgn.extents.x1, - draw_item->base.rgn.extents.y1, - draw_item->base.rgn.extents.x2, - draw_item->base.rgn.extents.y2); -} - static inline void red_create_surface_item(DisplayChannelClient *dcc, int surface_id); static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id); @@ -1575,43 +1416,6 @@ static inline void current_remove(RedWorker *worker, TreeItem *item) } } -static void current_tree_for_each(Ring *ring, void (*f)(TreeItem *, void *), void * data) -{ - RingItem *ring_item; - Ring *top_ring; - - if (!(ring_item = ring_get_head(ring))) { - return; - } - top_ring = ring; - - for (;;) { - TreeItem *now = SPICE_CONTAINEROF(ring_item, TreeItem, siblings_link); - - f(now, data); - - if (now->type == TREE_ITEM_TYPE_CONTAINER) { - Container *container = (Container *)now; - - if ((ring_item = ring_get_head(&container->items))) { - ring = &container->items; - continue; - } - } - for (;;) { - ring_item = ring_next(ring, &now->siblings_link); - if (ring_item) { - break; - } - if (ring == top_ring) { - return; - } - now = (TreeItem *)now->container; - ring = (now->container) ? &now->container->items : top_ring; - } - } -} - static void red_current_clear(RedWorker *worker, int surface_id) { RingItem *ring_item; @@ -8393,70 +8197,21 @@ static inline void red_push(RedWorker *worker) } } -typedef struct ShowTreeData { - RedWorker *worker; - int level; - Container *container; -} ShowTreeData; - -static void __show_tree_call(TreeItem *item, void *data) -{ - ShowTreeData *tree_data = data; - const char *item_prefix = "|--"; - int i; - - while (tree_data->container != item->container) { - spice_assert(tree_data->container); - tree_data->level--; - tree_data->container = tree_data->container->base.container; - } - - switch (item->type) { - case TREE_ITEM_TYPE_DRAWABLE: { - Drawable *drawable = SPICE_CONTAINEROF(item, Drawable, tree_item); - const int max_indent = 200; - char indent_str[max_indent + 1]; - int indent_str_len; - - for (i = 0; i < tree_data->level; i++) { - printf(" "); - } - printf(item_prefix, 0); - show_red_drawable(tree_data->worker, drawable->red_drawable, NULL); - for (i = 0; i < tree_data->level; i++) { - printf(" "); - } - printf("| "); - show_draw_item(tree_data->worker, &drawable->tree_item, NULL); - indent_str_len = MIN(max_indent, strlen(item_prefix) + tree_data->level * 2); - memset(indent_str, ' ', indent_str_len); - indent_str[indent_str_len] = 0; - region_dump(&item->rgn, indent_str); - printf("\n"); - break; - } - case TREE_ITEM_TYPE_CONTAINER: - tree_data->level++; - tree_data->container = (Container *)item; - break; - case TREE_ITEM_TYPE_SHADOW: - break; - } -} - void red_show_tree(RedWorker *worker) { int x; - ShowTreeData show_tree_data; - show_tree_data.worker = worker; - show_tree_data.level = 0; - show_tree_data.container = NULL; for (x = 0; x < NUM_SURFACES; ++x) { - if (worker->surfaces[x].context.canvas) { - current_tree_for_each(&worker->surfaces[x].current, __show_tree_call, - &show_tree_data); + if (!worker->surfaces[x].context.canvas) + continue; + + RingItem *it; + Ring *ring = &worker->surfaces[x].current; + RING_FOREACH(it, ring) { + TreeItem *now = SPICE_CONTAINEROF(it, TreeItem, siblings_link); + tree_item_dump(now); } + } } diff --git a/server/tree.c b/server/tree.c new file mode 100644 index 00000000..ed7d39ad --- /dev/null +++ b/server/tree.c @@ -0,0 +1,182 @@ +/* + Copyright (C) 2009-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include +#include "red_parse_qxl.h" +#include "display-channel.h" + +#include "tree.h" + +static const char *draw_type_to_str(uint8_t type) +{ + switch (type) { + case QXL_DRAW_FILL: + return "QXL_DRAW_FILL"; + case QXL_DRAW_OPAQUE: + return "QXL_DRAW_OPAQUE"; + case QXL_DRAW_COPY: + return "QXL_DRAW_COPY"; + case QXL_DRAW_TRANSPARENT: + return "QXL_DRAW_TRANSPARENT"; + case QXL_DRAW_ALPHA_BLEND: + return "QXL_DRAW_ALPHA_BLEND"; + case QXL_COPY_BITS: + return "QXL_COPY_BITS"; + case QXL_DRAW_BLEND: + return "QXL_DRAW_BLEND"; + case QXL_DRAW_BLACKNESS: + return "QXL_DRAW_BLACKNESS"; + case QXL_DRAW_WHITENESS: + return "QXL_DRAW_WHITENESS"; + case QXL_DRAW_INVERS: + return "QXL_DRAW_INVERS"; + case QXL_DRAW_ROP3: + return "QXL_DRAW_ROP3"; + case QXL_DRAW_COMPOSITE: + return "QXL_DRAW_COMPOSITE"; + case QXL_DRAW_STROKE: + return "QXL_DRAW_STROKE"; + case QXL_DRAW_TEXT: + return "QXL_DRAW_TEXT"; + default: + return "?"; + } +} + +static void show_red_drawable(RedDrawable *drawable, const char *prefix) +{ + if (prefix) { + printf("%s: ", prefix); + } + + printf("%s effect %d bbox(%d %d %d %d)", + draw_type_to_str(drawable->type), + drawable->effect, + drawable->bbox.top, + drawable->bbox.left, + drawable->bbox.bottom, + drawable->bbox.right); + + switch (drawable->type) { + case QXL_DRAW_FILL: + case QXL_DRAW_OPAQUE: + case QXL_DRAW_COPY: + case QXL_DRAW_TRANSPARENT: + case QXL_DRAW_ALPHA_BLEND: + case QXL_COPY_BITS: + case QXL_DRAW_BLEND: + case QXL_DRAW_BLACKNESS: + case QXL_DRAW_WHITENESS: + case QXL_DRAW_INVERS: + case QXL_DRAW_ROP3: + case QXL_DRAW_COMPOSITE: + case QXL_DRAW_STROKE: + case QXL_DRAW_TEXT: + break; + default: + spice_error("bad drawable type"); + } + printf("\n"); +} + +static void show_draw_item(DrawItem *draw_item, const char *prefix) +{ + if (prefix) { + printf("%s: ", prefix); + } + printf("effect %d bbox(%d %d %d %d)\n", + draw_item->effect, + draw_item->base.rgn.extents.x1, + draw_item->base.rgn.extents.y1, + draw_item->base.rgn.extents.x2, + draw_item->base.rgn.extents.y2); +} + +typedef struct DumpItem { + int level; + Container *container; +} DumpItem; + +static void dump_item(TreeItem *item, void *data) +{ + DumpItem *di = data; + const char *item_prefix = "|--"; + int i; + + if (di->container) { + while (di->container != item->container) { + di->level--; + di->container = di->container->base.container; + } + } + + switch (item->type) { + case TREE_ITEM_TYPE_DRAWABLE: { + Drawable *drawable = SPICE_CONTAINEROF(item, Drawable, tree_item); + const int max_indent = 200; + char indent_str[max_indent + 1]; + int indent_str_len; + + for (i = 0; i < di->level; i++) { + printf(" "); + } + printf(item_prefix, 0); + show_red_drawable(drawable->red_drawable, NULL); + for (i = 0; i < di->level; i++) { + printf(" "); + } + printf("| "); + show_draw_item(&drawable->tree_item, NULL); + indent_str_len = MIN(max_indent, strlen(item_prefix) + di->level * 2); + memset(indent_str, ' ', indent_str_len); + indent_str[indent_str_len] = 0; + region_dump(&item->rgn, indent_str); + printf("\n"); + break; + } + case TREE_ITEM_TYPE_CONTAINER: + di->level++; + di->container = (Container *)item; + break; + case TREE_ITEM_TYPE_SHADOW: + break; + } +} + +static void tree_foreach(TreeItem *item, void (*f)(TreeItem *, void *), void * data) +{ + if (!item) + return; + + f(item, data); + + if (item->type == TREE_ITEM_TYPE_CONTAINER) { + Container *container = (Container*)item; + RingItem *it; + + RING_FOREACH(it, &container->items) { + tree_foreach(SPICE_CONTAINEROF(it, TreeItem, siblings_link), f, data); + } + } +} + +void tree_item_dump(TreeItem *item) +{ + DumpItem di = { 0, }; + + spice_return_if_fail(item != NULL); + tree_foreach(item, dump_item, &di); +} diff --git a/server/tree.h b/server/tree.h new file mode 100644 index 00000000..8cd7b05f --- /dev/null +++ b/server/tree.h @@ -0,0 +1,111 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef TREE_H_ +# define TREE_H_ + +#include +#include "common/region.h" +#include "common/ring.h" + +enum { + TREE_ITEM_TYPE_NONE, + TREE_ITEM_TYPE_DRAWABLE, + TREE_ITEM_TYPE_CONTAINER, + TREE_ITEM_TYPE_SHADOW, + + TREE_ITEM_TYPE_LAST, +}; + +typedef struct TreeItem TreeItem; +typedef struct Shadow Shadow; +typedef struct Container Container; +typedef struct DrawItem DrawItem; + +/* TODO consider GNode instead */ +struct TreeItem { + RingItem siblings_link; + uint32_t type; + Container *container; + QRegion rgn; +}; + +struct Shadow { + TreeItem base; + QRegion on_hold; + DrawItem* owner; +}; + +struct Container { + TreeItem base; + Ring items; +}; + +struct DrawItem { + TreeItem base; + uint8_t effect; + uint8_t container_root; + Shadow *shadow; +}; + +#define IS_DRAW_ITEM(item) ((item)->type == TREE_ITEM_TYPE_DRAWABLE) + +typedef enum { + BITMAP_GRADUAL_INVALID, + BITMAP_GRADUAL_NOT_AVAIL, + BITMAP_GRADUAL_LOW, + BITMAP_GRADUAL_MEDIUM, + BITMAP_GRADUAL_HIGH, +} BitmapGradualType; + +typedef struct DependItem { + Drawable *drawable; + RingItem ring_item; +} DependItem; + +struct Drawable { + uint8_t refs; + RingItem surface_list_link; + RingItem list_link; + DrawItem tree_item; + Ring pipes; + PipeItem *pipe_item_rest; + uint32_t size_pipe_item_rest; + RedDrawable *red_drawable; + + Ring glz_ring; + + red_time_t creation_time; + int frames_count; + int gradual_frames_count; + int last_gradual_frame; + Stream *stream; + Stream *sized_stream; + int streamable; + BitmapGradualType copy_bitmap_graduality; + uint32_t group_id; + DependItem depend_items[3]; + + int surface_id; + int surfaces_dest[3]; + + uint32_t process_commands_generation; +}; + +void tree_item_dump (TreeItem *item); + +#endif /* TREE_H_ */ -- cgit