tree: move that to a separate unit

Acked-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
Marc-André Lureau 2013-09-10 22:59:31 +02:00 committed by Frediano Ziglio
parent 9e42647101
commit 372eb0072a
5 changed files with 311 additions and 255 deletions

View File

@ -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)

View File

@ -18,9 +18,15 @@
#ifndef RED_WORKER_CLIENT_H_
# define RED_WORKER_CLIENT_H_
#include <setjmp.h>
#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;

View File

@ -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);
}
}
}

182
server/tree.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <spice/qxl_dev.h>
#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);
}

111
server/tree.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef TREE_H_
# define TREE_H_
#include <stdint.h>
#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_ */