From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> Author: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> --- server/Makefile.am | 1 + server/dcc.c | 62 +++++++++++++++++++++++++++ server/red_worker.c | 121 ++-------------------------------------------------- server/utils.c | 46 ++++++++++++++++++++ server/utils.h | 4 ++ 5 files changed, 116 insertions(+), 118 deletions(-) create mode 100644 server/utils.c diff --git a/server/Makefile.am b/server/Makefile.am index 669664a..64d0e7d 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -135,6 +135,7 @@ libspice_server_la_SOURCES = \ tree.c \ spice-bitmap-utils.h \ spice-bitmap-utils.c \ + utils.c \ utils.h \ stream.c \ stream.h \ diff --git a/server/dcc.c b/server/dcc.c index a17fa7d..b59029d 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -68,6 +68,68 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id) red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &create->pipe_item); } +// adding the pipe item after pos. If pos == NULL, adding to head. +ImageItem *dcc_add_surface_area_image(DisplayChannelClient *dcc, int surface_id, + SpiceRect *area, PipeItem *pos, int can_lossy) +{ + DisplayChannel *display = DCC_TO_DC(dcc); + RedChannel *channel = RED_CHANNEL(display); + RedSurface *surface = &display->surfaces[surface_id]; + SpiceCanvas *canvas = surface->context.canvas; + ImageItem *item; + int stride; + int width; + int height; + int bpp; + int all_set; + + spice_return_val_if_fail(area, NULL); + + width = area->right - area->left; + height = area->bottom - area->top; + bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8; + stride = width * bpp; + + item = (ImageItem *)spice_malloc_n_m(height, stride, sizeof(ImageItem)); + + red_channel_pipe_item_init(channel, &item->link, PIPE_ITEM_TYPE_IMAGE); + + item->refs = 1; + item->surface_id = surface_id; + item->image_format = + spice_bitmap_from_surface_type(surface->context.format); + item->image_flags = 0; + item->pos.x = area->left; + item->pos.y = area->top; + item->width = width; + item->height = height; + item->stride = stride; + item->top_down = surface->context.top_down; + item->can_lossy = can_lossy; + + canvas->ops->read_bits(canvas, item->data, stride, area); + + /* For 32bit non-primary surfaces we need to keep any non-zero + high bytes as the surface may be used as source to an alpha_blend */ + if (!is_primary_surface(display, surface_id) && + item->image_format == SPICE_BITMAP_FMT_32BIT && + rgb32_data_has_alpha(item->width, item->height, item->stride, item->data, &all_set)) { + if (all_set) { + item->image_flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET; + } else { + item->image_format = SPICE_BITMAP_FMT_RGBA; + } + } + + if (pos) { + red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &item->link, pos); + } else { + red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &item->link); + } + + return item; +} + void dcc_push_surface_image(DisplayChannelClient *dcc, int surface_id) { DisplayChannel *display; diff --git a/server/red_worker.c b/server/red_worker.c index 377eb36..09ebc0d 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -226,12 +226,8 @@ static int cursor_is_connected(RedWorker *worker) red_channel_is_connected(RED_CHANNEL(worker->cursor_channel)); } -static inline PipeItem *red_pipe_get_tail(DisplayChannelClient *dcc) +static PipeItem *dcc_get_tail(DisplayChannelClient *dcc) { - if (!dcc) { - return NULL; - } - return (PipeItem*)ring_get_tail(&RED_CHANNEL_CLIENT(dcc)->pipe); } @@ -249,25 +245,6 @@ void red_pipes_remove_drawable(Drawable *drawable) } } -static inline void red_pipe_add_image_item(DisplayChannelClient *dcc, ImageItem *item) -{ - if (!dcc) { - return; - } - item->refs++; - red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &item->link); -} - -static inline void red_pipe_add_image_item_after(DisplayChannelClient *dcc, ImageItem *item, - PipeItem *pos) -{ - if (!dcc) { - return; - } - item->refs++; - red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &item->link, pos); -} - static void release_image_item(ImageItem *item) { if (!--item->refs) { @@ -811,34 +788,6 @@ static void red_get_area(DisplayChannel *display, int surface_id, const SpiceRec canvas->ops->read_bits(canvas, dest, dest_stride, area); } -static int rgb32_data_has_alpha(int width, int height, size_t stride, - uint8_t *data, int *all_set_out) -{ - uint32_t *line, *end, alpha; - int has_alpha; - - has_alpha = FALSE; - while (height-- > 0) { - line = (uint32_t *)data; - end = line + width; - data += stride; - while (line != end) { - alpha = *line & 0xff000000U; - if (alpha != 0) { - has_alpha = TRUE; - if (alpha != 0xff000000U) { - *all_set_out = FALSE; - return TRUE; - } - } - line++; - } - } - - *all_set_out = has_alpha; - return has_alpha; -} - static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable) { DisplayChannel *display = worker->display_channel; @@ -1677,70 +1626,6 @@ void display_channel_current_flush(DisplayChannel *display, int surface_id) current_remove_all(display, surface_id); } -// adding the pipe item after pos. If pos == NULL, adding to head. -ImageItem *dcc_add_surface_area_image(DisplayChannelClient *dcc, int surface_id, - SpiceRect *area, PipeItem *pos, int can_lossy) -{ - DisplayChannel *display = DCC_TO_DC(dcc); - RedChannel *channel = RED_CHANNEL(display); - RedSurface *surface = &display->surfaces[surface_id]; - SpiceCanvas *canvas = surface->context.canvas; - ImageItem *item; - int stride; - int width; - int height; - int bpp; - int all_set; - - spice_assert(area); - - width = area->right - area->left; - height = area->bottom - area->top; - bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8; - stride = width * bpp; - - item = (ImageItem *)spice_malloc_n_m(height, stride, sizeof(ImageItem)); - - red_channel_pipe_item_init(channel, &item->link, PIPE_ITEM_TYPE_IMAGE); - - item->refs = 1; - item->surface_id = surface_id; - item->image_format = - spice_bitmap_from_surface_type(surface->context.format); - item->image_flags = 0; - item->pos.x = area->left; - item->pos.y = area->top; - item->width = width; - item->height = height; - item->stride = stride; - item->top_down = surface->context.top_down; - item->can_lossy = can_lossy; - - canvas->ops->read_bits(canvas, item->data, stride, area); - - /* For 32bit non-primary surfaces we need to keep any non-zero - high bytes as the surface may be used as source to an alpha_blend */ - if (!is_primary_surface(display, surface_id) && - item->image_format == SPICE_BITMAP_FMT_32BIT && - rgb32_data_has_alpha(item->width, item->height, item->stride, item->data, &all_set)) { - if (all_set) { - item->image_flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET; - } else { - item->image_format = SPICE_BITMAP_FMT_RGBA; - } - } - - if (!pos) { - red_pipe_add_image_item(dcc, item); - } else { - red_pipe_add_image_item_after(dcc, item, pos); - } - - release_image_item(item); - - return item; -} - static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable) { SpiceMsgDisplayBase base; @@ -2376,7 +2261,7 @@ static void red_add_lossless_drawable_dependencies(RedChannelClient *rcc, // will be executed before the current drawable for (i = 0; i < num_deps; i++) { dcc_add_surface_area_image(dcc, deps_surfaces_ids[i], deps_areas[i], - red_pipe_get_tail(dcc), FALSE); + dcc_get_tail(dcc), FALSE); } } else { @@ -2397,7 +2282,7 @@ static void red_add_lossless_drawable_dependencies(RedChannelClient *rcc, } dcc_add_surface_area_image(dcc, drawable->surface_id, &drawable->bbox, - red_pipe_get_tail(dcc), TRUE); + dcc_get_tail(dcc), TRUE); } } diff --git a/server/utils.c b/server/utils.c new file mode 100644 index 0000000..6840118 --- /dev/null +++ b/server/utils.c @@ -0,0 +1,46 @@ +/* + 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 <glib.h> +#include "utils.h" + +int rgb32_data_has_alpha(int width, int height, size_t stride, + uint8_t *data, int *all_set_out) +{ + uint32_t *line, *end, alpha; + int has_alpha; + + has_alpha = FALSE; + while (height-- > 0) { + line = (uint32_t *)data; + end = line + width; + data += stride; + while (line != end) { + alpha = *line & 0xff000000U; + if (alpha != 0) { + has_alpha = TRUE; + if (alpha != 0xff000000U) { + *all_set_out = FALSE; + return TRUE; + } + } + line++; + } + } + + *all_set_out = has_alpha; + return has_alpha; +} diff --git a/server/utils.h b/server/utils.h index cae03d4..db4242d 100644 --- a/server/utils.h +++ b/server/utils.h @@ -18,6 +18,7 @@ #ifndef UTILS_H_ # define UTILS_H_ +#include <stdint.h> #include <time.h> #include <stdint.h> @@ -32,4 +33,7 @@ static inline red_time_t red_get_monotonic_time(void) return (red_time_t) time.tv_sec * (1000 * 1000 * 1000) + time.tv_nsec; } +int rgb32_data_has_alpha(int width, int height, size_t stride, + uint8_t *data, int *all_set_out); + #endif /* UTILS_H_ */ -- 2.4.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel