summaryrefslogtreecommitdiffstats
path: root/common/sw_canvas.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/sw_canvas.c')
-rw-r--r--common/sw_canvas.c1327
1 files changed, 0 insertions, 1327 deletions
diff --git a/common/sw_canvas.c b/common/sw_canvas.c
deleted file mode 100644
index 8eabc896..00000000
--- a/common/sw_canvas.c
+++ /dev/null
@@ -1,1327 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 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/>.
-*/
-#ifdef HAVE_CONFIG_H
-#ifdef __MINGW32__
-#undef HAVE_STDLIB_H
-#endif
-#include <config.h>
-#endif
-
-#ifndef SPICE_CANVAS_INTERNAL
-#error "This file shouldn't be compiled directly"
-#endif
-
-#include <math.h>
-#include "sw_canvas.h"
-#define CANVAS_USE_PIXMAN
-#define CANVAS_SINGLE_INSTANCE
-#include "canvas_base.c"
-#include "rect.h"
-#include "region.h"
-#include "pixman_utils.h"
-
-typedef struct SwCanvas SwCanvas;
-
-struct SwCanvas {
- CanvasBase base;
- uint32_t *private_data;
- int private_data_size;
- pixman_image_t *image;
-};
-
-static pixman_image_t *canvas_get_pixman_brush(SwCanvas *canvas,
- SpiceBrush *brush)
-{
- switch (brush->type) {
- case SPICE_BRUSH_TYPE_SOLID: {
- uint32_t color = brush->u.color;
- pixman_color_t c;
-
- c.blue = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
- color >>= canvas->base.color_shift;
- c.green = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
- color >>= canvas->base.color_shift;
- c.red = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
- c.alpha = 0xffff;
-
- return pixman_image_create_solid_fill(&c);
- }
- case SPICE_BRUSH_TYPE_PATTERN: {
- SwCanvas *surface_canvas;
- pixman_image_t* surface;
- pixman_transform_t t;
-
- surface_canvas = (SwCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat);
- if (surface_canvas) {
- surface = surface_canvas->image;
- surface = pixman_image_ref(surface);
- } else {
- surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE);
- }
- pixman_transform_init_translate(&t,
- pixman_int_to_fixed(-brush->u.pattern.pos.x),
- pixman_int_to_fixed(-brush->u.pattern.pos.y));
- pixman_image_set_transform(surface, &t);
- pixman_image_set_repeat(surface, PIXMAN_REPEAT_NORMAL);
- return surface;
- }
- case SPICE_BRUSH_TYPE_NONE:
- return NULL;
- default:
- CANVAS_ERROR("invalid brush type");
- }
-}
-
-static pixman_image_t *get_image(SpiceCanvas *canvas)
-{
- SwCanvas *sw_canvas = (SwCanvas *)canvas;
-
- pixman_image_ref(sw_canvas->image);
-
- return sw_canvas->image;
-}
-
-static void copy_region(SpiceCanvas *spice_canvas,
- pixman_region32_t *dest_region,
- int dx, int dy)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *dest_rects;
- int n_rects;
- int i, j, end_line;
-
- dest_rects = pixman_region32_rectangles(dest_region, &n_rects);
-
- if (dy > 0) {
- if (dx >= 0) {
- /* south-east: copy x and y in reverse order */
- for (i = n_rects - 1; i >= 0; i--) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
- dest_rects[i].x2 - dest_rects[i].x1,
- dest_rects[i].y2 - dest_rects[i].y1,
- dest_rects[i].x1, dest_rects[i].y1);
- }
- } else {
- /* south-west: Copy y in reverse order, but x in forward order */
- i = n_rects - 1;
-
- while (i >= 0) {
- /* Copy all rects with same y in forward order */
- for (end_line = i - 1;
- end_line >= 0 && dest_rects[end_line].y1 == dest_rects[i].y1;
- end_line--) {
- }
- for (j = end_line + 1; j <= i; j++) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
- dest_rects[j].x2 - dest_rects[j].x1,
- dest_rects[j].y2 - dest_rects[j].y1,
- dest_rects[j].x1, dest_rects[j].y1);
- }
- i = end_line;
- }
- }
- } else {
- if (dx > 0) {
- /* north-east: copy y in forward order, but x in reverse order */
- i = 0;
-
- while (i < n_rects) {
- /* Copy all rects with same y in reverse order */
- for (end_line = i;
- end_line < n_rects && dest_rects[end_line].y1 == dest_rects[i].y1;
- end_line++) {
- }
- for (j = end_line - 1; j >= i; j--) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
- dest_rects[j].x2 - dest_rects[j].x1,
- dest_rects[j].y2 - dest_rects[j].y1,
- dest_rects[j].x1, dest_rects[j].y1);
- }
- i = end_line;
- }
- } else {
- /* north-west: Copy x and y in forward order */
- for (i = 0; i < n_rects; i++) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
- dest_rects[i].x2 - dest_rects[i].x1,
- dest_rects[i].y2 - dest_rects[i].y1,
- dest_rects[i].x1, dest_rects[i].y1);
- }
- }
- }
-}
-
-static void fill_solid_spans(SpiceCanvas *spice_canvas,
- SpicePoint *points,
- int *widths,
- int n_spans,
- uint32_t color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_spans; i++) {
- spice_pixman_fill_rect(canvas->image,
- points[i].x, points[i].y,
- widths[i],
- 1,
- color);
- }
-}
-
-static void fill_solid_rects(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- uint32_t color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_fill_rect(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- color);
- }
-}
-
-static void fill_solid_rects_rop(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- uint32_t color,
- SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_fill_rect_rop(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- color, rop);
- }
-}
-
-static void __fill_tiled_rects(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_tile_rect(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- tile, offset_x, offset_y);
- }
-}
-
-static void fill_tiled_rects(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y)
-{
- __fill_tiled_rects(spice_canvas, rects, n_rects, tile, offset_x, offset_y);
-}
-
-static void fill_tiled_rects_from_surface(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __fill_tiled_rects(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x,
- offset_y);
-}
-
-static void __fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_tile_rect_rop(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- tile, offset_x, offset_y,
- rop);
- }
-}
-static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- __fill_tiled_rects_rop(spice_canvas, rects, n_rects, tile, offset_x, offset_y, rop);
-}
-
-static void fill_tiled_rects_rop_from_surface(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __fill_tiled_rects_rop(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x,
- offset_y, rop);
-}
-
-/* Some pixman implementations of OP_OVER on xRGB32 sets
- the high bit to 0xff (which is the right value if the
- destination was ARGB32, and it should be ignored for
- xRGB32. However, this fills our alpha bits with
- data that is not wanted or expected by windows, and its
- causing us to send rgba images rather than rgb images to
- the client. So, we manually clear these bytes. */
-static void clear_dest_alpha(pixman_image_t *dest,
- int x, int y,
- int width, int height)
-{
- uint32_t *data;
- int stride;
- int w, h;
-
- w = pixman_image_get_width(dest);
- h = pixman_image_get_height(dest);
-
- if (x + width <= 0 || x >= w ||
- y + height <= 0 || y >= h ||
- width == 0 || height == 0) {
- return;
- }
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (x + width > w) {
- width = w - x;
- }
-
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (y + height > h) {
- height = h - y;
- }
-
- stride = pixman_image_get_stride(dest);
- data = (uint32_t *) (
- (uint8_t *)pixman_image_get_data(dest) + y * stride + 4 * x);
-
- if ((*data & 0xff000000U) == 0xff000000U) {
- spice_pixman_fill_rect_rop(dest,
- x, y, width, height,
- 0x00ffffff, SPICE_ROP_AND);
- }
-}
-
-static void __blit_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *rects;
- int n_rects, i;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- int src_x, src_y, dest_x, dest_y, width, height;
-
- dest_x = rects[i].x1;
- dest_y = rects[i].y1;
- width = rects[i].x2 - rects[i].x1;
- height = rects[i].y2 - rects[i].y1;
-
- src_x = rects[i].x1 - offset_x;
- src_y = rects[i].y1 - offset_y;
-
- spice_pixman_blit(canvas->image,
- src_image,
- src_x, src_y,
- dest_x, dest_y,
- width, height);
- }
-}
-
-static void blit_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y)
-{
- __blit_image(spice_canvas, region, src_image, offset_x, offset_y);
-}
-
-static void blit_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __blit_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y);
-}
-
-static void __blit_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *rects;
- int n_rects, i;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- int src_x, src_y, dest_x, dest_y, width, height;
-
- dest_x = rects[i].x1;
- dest_y = rects[i].y1;
- width = rects[i].x2 - rects[i].x1;
- height = rects[i].y2 - rects[i].y1;
-
- src_x = rects[i].x1 - offset_x;
- src_y = rects[i].y1 - offset_y;
-
- spice_pixman_blit_rop(canvas->image,
- src_image,
- src_x, src_y,
- dest_x, dest_y,
- width, height, rop);
- }
-}
-
-static void blit_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- __blit_image_rop(spice_canvas, region, src_image, offset_x, offset_y, rop);
-}
-
-static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __blit_image_rop(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, rop);
-}
-
-
-
-static void __scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- pixman_image_set_clip_region32(canvas->image, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
- scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
- PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, canvas->image,
- 0, 0, /* src */
- 0, 0, /* mask */
- dest_x, dest_y, /* dst */
- dest_width, dest_height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- pixman_image_set_clip_region32(canvas->image, NULL);
-}
-
-static void scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode)
-{
- __scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, dest_y,
- dest_width,dest_height,scale_mode);
-}
-
-static void scale_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width,
- src_height, dest_x, dest_y, dest_width,dest_height,scale_mode);
-}
-
-static void __scale_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_image_t *scaled;
- pixman_box32_t *rects;
- int n_rects, i;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- scaled = pixman_image_create_bits(spice_pixman_image_get_format(src),
- dest_width,
- dest_height,
- NULL, 0);
-
- pixman_region32_translate(region, -dest_x, -dest_y);
- pixman_image_set_clip_region32(scaled, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
- scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
- PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, scaled,
- 0, 0, /* src */
- 0, 0, /* mask */
- 0, 0, /* dst */
- dest_width,
- dest_height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- /* Translate back */
- pixman_region32_translate(region, dest_x, dest_y);
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_blit_rop(canvas->image,
- scaled,
- rects[i].x1 - dest_x,
- rects[i].y1 - dest_y,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- rop);
- }
-
- pixman_image_unref(scaled);
-}
-
-static void scale_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop)
-{
- __scale_image_rop(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
- dest_y, dest_width, dest_height, scale_mode, rop);
-}
-
-static void scale_image_rop_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __scale_image_rop(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width,
- src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop);
-}
-
-static pixman_image_t *canvas_get_as_surface(SwCanvas *canvas,
- int with_alpha)
-{
- pixman_image_t *target;
-
- if (with_alpha &&
- canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
- target = pixman_image_create_bits(PIXMAN_a8r8g8b8,
- pixman_image_get_width(canvas->image),
- pixman_image_get_height(canvas->image),
- pixman_image_get_data(canvas->image),
- pixman_image_get_stride(canvas->image));
- } else {
- target = pixman_image_ref(canvas->image);
- }
-
- return target;
-}
-
-static void __blend_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_image_t *mask, *dest;
-
- dest = canvas_get_as_surface(canvas, dest_has_alpha);
-
- pixman_image_set_clip_region32(dest, region);
-
- mask = NULL;
- if (overall_alpha != 0xff) {
- pixman_color_t color = { 0 };
- color.alpha = overall_alpha * 0x101;
- mask = pixman_image_create_solid_fill(&color);
- }
-
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-
- pixman_image_composite32(PIXMAN_OP_OVER,
- src, mask, dest,
- src_x, src_y, /* src */
- 0, 0, /* mask */
- dest_x, dest_y, /* dst */
- width,
- height);
-
- if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
- !dest_has_alpha) {
- clear_dest_alpha(dest, dest_x, dest_y, width, height);
- }
-
- if (mask) {
- pixman_image_unref(mask);
- }
-
- pixman_image_set_clip_region32(dest, NULL);
- pixman_image_unref(dest);
-}
-
-static void blend_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
-{
- __blend_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y,
- dest_x, dest_y, width, height,
- overall_alpha);
-}
-
-static void blend_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- SpiceCanvas *surface_canvas,
- int src_has_alpha,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- pixman_image_t *src;
-
- src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha);
- __blend_image(spice_canvas, region, dest_has_alpha,
- src, src_x, src_y,
- dest_x, dest_y,
- width, height, overall_alpha);
- pixman_image_unref(src);
-}
-
-static void __blend_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_image_t *mask, *dest;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- dest = canvas_get_as_surface(canvas, dest_has_alpha);
-
- pixman_image_set_clip_region32(dest, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- mask = NULL;
- if (overall_alpha != 0xff) {
- pixman_color_t color = { 0 };
- color.alpha = overall_alpha * 0x101;
- mask = pixman_image_create_solid_fill(&color);
- }
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
- scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
- PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_OVER,
- src, mask, dest,
- 0, 0, /* src */
- 0, 0, /* mask */
- dest_x, dest_y, /* dst */
- dest_width, dest_height);
-
- if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
- !dest_has_alpha) {
- clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height);
- }
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- if (mask) {
- pixman_image_unref(mask);
- }
-
- pixman_image_set_clip_region32(dest, NULL);
- pixman_image_unref(dest);
-}
-
-static void blend_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha)
-{
- __blend_scale_image(spice_canvas, region, dest_has_alpha,
- src, src_x, src_y, src_width, src_height,
- dest_x, dest_y, dest_width, dest_height,
- scale_mode, overall_alpha);
-}
-
-static void blend_scale_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- SpiceCanvas *surface_canvas,
- int src_has_alpha,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- pixman_image_t *src;
-
- src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha);
- __blend_scale_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, src_width,
- src_height, dest_x, dest_y, dest_width, dest_height, scale_mode,
- overall_alpha);
- pixman_image_unref(src);
-}
-
-static void __colorkey_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- uint32_t transparent_color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *rects;
- int n_rects, i;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- int src_x, src_y, dest_x, dest_y, width, height;
-
- dest_x = rects[i].x1;
- dest_y = rects[i].y1;
- width = rects[i].x2 - rects[i].x1;
- height = rects[i].y2 - rects[i].y1;
-
- src_x = rects[i].x1 - offset_x;
- src_y = rects[i].y1 - offset_y;
-
- spice_pixman_blit_colorkey(canvas->image,
- src_image,
- src_x, src_y,
- dest_x, dest_y,
- width, height,
- transparent_color);
- }
-}
-
-static void colorkey_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- uint32_t transparent_color)
-{
- __colorkey_image(spice_canvas, region, src_image, offset_x, offset_y, transparent_color);
-}
-
-static void colorkey_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y,
- uint32_t transparent_color)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __colorkey_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y,
- transparent_color);
-}
-
-static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_image_t *scaled;
- pixman_box32_t *rects;
- int n_rects, i;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- scaled = pixman_image_create_bits(spice_pixman_image_get_format (src),
- dest_width,
- dest_height,
- NULL, 0);
-
- pixman_region32_translate(region, -dest_x, -dest_y);
- pixman_image_set_clip_region32(scaled, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- pixman_image_set_filter(src,
- PIXMAN_FILTER_NEAREST,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, scaled,
- 0, 0, /* src */
- 0, 0, /* mask */
- 0, 0, /* dst */
- dest_width,
- dest_height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- /* Translate back */
- pixman_region32_translate(region, dest_x, dest_y);
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_blit_colorkey(canvas->image,
- scaled,
- rects[i].x1 - dest_x,
- rects[i].y1 - dest_y,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- transparent_color);
- }
-
- pixman_image_unref(scaled);
-}
-
-static void colorkey_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color)
-{
- __colorkey_scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
- dest_y, dest_width, dest_height, transparent_color);
-}
-
-static void colorkey_scale_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __colorkey_scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y,
- src_width, src_height, dest_x, dest_y, dest_width, dest_height,
- transparent_color);
-}
-
-static void canvas_put_image(SpiceCanvas *spice_canvas,
-#ifdef WIN32
- HDC dc,
-#endif
- const SpiceRect *dest, const uint8_t *src_data,
- uint32_t src_width, uint32_t src_height, int src_stride,
- const QRegion *clip)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_image_t *src;
- uint32_t dest_width;
- uint32_t dest_height;
- double sx, sy;
- pixman_transform_t transform;
-
- src = pixman_image_create_bits(PIXMAN_x8r8g8b8,
- src_width,
- src_height,
- (uint32_t*)src_data,
- src_stride);
-
-
- if (clip) {
- pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip);
- }
-
- dest_width = dest->right - dest->left;
- dest_height = dest->bottom - dest->top;
-
- if (dest_width != src_width || dest_height != src_height) {
- sx = (double)(src_width) / (dest_width);
- sy = (double)(src_height) / (dest_height);
-
- pixman_transform_init_scale(&transform,
- pixman_double_to_fixed(sx),
- pixman_double_to_fixed(sy));
- pixman_image_set_transform(src, &transform);
- pixman_image_set_filter(src,
- PIXMAN_FILTER_NEAREST,
- NULL, 0);
- }
-
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, canvas->image,
- 0, 0, /* src */
- 0, 0, /* mask */
- dest->left, dest->top, /* dst */
- dest_width, dest_height);
-
-
- if (clip) {
- pixman_image_set_clip_region32(canvas->image, NULL);
- }
- pixman_image_unref(src);
-}
-
-
-static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox,
- SpiceClip *clip, SpiceText *text)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_region32_t dest_region;
- pixman_image_t *str_mask, *brush;
- SpiceString *str;
- SpicePoint pos;
- int depth;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(&canvas->base, &dest_region, clip);
-
- if (!pixman_region32_not_empty(&dest_region)) {
- touch_brush(&canvas->base, &text->fore_brush);
- touch_brush(&canvas->base, &text->back_brush);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- if (!rect_is_empty(&text->back_area)) {
- pixman_region32_t back_region;
-
- /* Nothing else makes sense for text and we should deprecate it
- * and actually it means OVER really */
- ASSERT(text->fore_mode == SPICE_ROPD_OP_PUT);
-
- pixman_region32_init_rect(&back_region,
- text->back_area.left,
- text->back_area.top,
- text->back_area.right - text->back_area.left,
- text->back_area.bottom - text->back_area.top);
-
- pixman_region32_intersect(&back_region, &back_region, &dest_region);
-
- if (pixman_region32_not_empty(&back_region)) {
- draw_brush(spice_canvas, &back_region, &text->back_brush, SPICE_ROP_COPY);
- }
-
- pixman_region32_fini(&back_region);
- }
- str = (SpiceString *)SPICE_GET_ADDRESS(text->str);
-
- if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
- depth = 1;
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
- depth = 4;
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) {
- WARN("untested path A8 glyphs");
- depth = 8;
- } else {
- WARN("unsupported path vector glyphs");
- pixman_region32_fini (&dest_region);
- return;
- }
-
- brush = canvas_get_pixman_brush(canvas, &text->fore_brush);
-
- str_mask = canvas_get_str_mask(&canvas->base, str, depth, &pos);
- if (brush) {
- pixman_image_set_clip_region32(canvas->image, &dest_region);
-
- pixman_image_composite32(PIXMAN_OP_OVER,
- brush,
- str_mask,
- canvas->image,
- 0, 0,
- 0, 0,
- pos.x, pos.y,
- pixman_image_get_width(str_mask),
- pixman_image_get_height(str_mask));
- if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
- clear_dest_alpha(canvas->image, pos.x, pos.y,
- pixman_image_get_width(str_mask),
- pixman_image_get_height(str_mask));
- }
- pixman_image_unref(brush);
-
- pixman_image_set_clip_region32(canvas->image, NULL);
- }
- pixman_image_unref(str_mask);
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest,
- int dest_stride, const SpiceRect *area)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_image_t* surface;
- uint8_t *src;
- int src_stride;
- uint8_t *dest_end;
- int bpp;
-
- ASSERT(canvas && area);
-
- surface = canvas->image;
-
- bpp = spice_pixman_image_get_bpp(surface) / 8;
-
- src_stride = pixman_image_get_stride(surface);
- src = (uint8_t *)pixman_image_get_data(surface) +
- area->top * src_stride + area->left * bpp;
- dest_end = dest + (area->bottom - area->top) * dest_stride;
- for (; dest != dest_end; dest += dest_stride, src += src_stride) {
- memcpy(dest, src, (area->right - area->left) * bpp);
- }
-}
-
-static void canvas_clear(SpiceCanvas *spice_canvas)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- spice_pixman_fill_rect(canvas->image,
- 0, 0,
- pixman_image_get_width(canvas->image),
- pixman_image_get_height(canvas->image),
- 0);
-}
-
-static void canvas_destroy(SpiceCanvas *spice_canvas)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- if (!canvas) {
- return;
- }
- pixman_image_unref(canvas->image);
- canvas_base_destroy(&canvas->base);
- free(canvas->private_data);
- free(canvas);
-}
-
-static int need_init = 1;
-static SpiceCanvasOps sw_canvas_ops;
-
-static SpiceCanvas *canvas_create_common(pixman_image_t *image,
- uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- SwCanvas *canvas;
-
- if (need_init) {
- return NULL;
- }
- spice_pixman_image_set_format(image,
- spice_surface_format_to_pixman (format));
-
- canvas = spice_new0(SwCanvas, 1);
- canvas_base_init(&canvas->base, &sw_canvas_ops,
- pixman_image_get_width (image),
- pixman_image_get_height (image),
- format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
- canvas->private_data = NULL;
- canvas->private_data_size = 0;
-
- canvas->image = image;
-
- return (SpiceCanvas *)canvas;
-}
-
-SpiceCanvas *canvas_create(int width, int height, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- pixman_image_t *image;
-
- image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
- width, height, NULL, 0);
-
- return canvas_create_common(image, format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
-}
-
-SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
- uint8_t *data, int stride
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- pixman_image_t *image;
-
- image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
- width, height, (uint32_t *)data, stride);
-
- return canvas_create_common(image, format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
-}
-
-void sw_canvas_init(void) //unsafe global function
-{
- if (!need_init) {
- return;
- }
- need_init = 0;
-
- canvas_base_init_ops(&sw_canvas_ops);
- sw_canvas_ops.draw_text = canvas_draw_text;
- sw_canvas_ops.put_image = canvas_put_image;
- sw_canvas_ops.clear = canvas_clear;
- sw_canvas_ops.read_bits = canvas_read_bits;
- sw_canvas_ops.destroy = canvas_destroy;
-
- sw_canvas_ops.fill_solid_spans = fill_solid_spans;
- sw_canvas_ops.fill_solid_rects = fill_solid_rects;
- sw_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop;
- sw_canvas_ops.fill_tiled_rects = fill_tiled_rects;
- sw_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface;
- sw_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop;
- sw_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface;
- sw_canvas_ops.blit_image = blit_image;
- sw_canvas_ops.blit_image_from_surface = blit_image_from_surface;
- sw_canvas_ops.blit_image_rop = blit_image_rop;
- sw_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface;
- sw_canvas_ops.scale_image = scale_image;
- sw_canvas_ops.scale_image_from_surface = scale_image_from_surface;
- sw_canvas_ops.scale_image_rop = scale_image_rop;
- sw_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface;
- sw_canvas_ops.blend_image = blend_image;
- sw_canvas_ops.blend_image_from_surface = blend_image_from_surface;
- sw_canvas_ops.blend_scale_image = blend_scale_image;
- sw_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface;
- sw_canvas_ops.colorkey_image = colorkey_image;
- sw_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface;
- sw_canvas_ops.colorkey_scale_image = colorkey_scale_image;
- sw_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface;
- sw_canvas_ops.copy_region = copy_region;
- sw_canvas_ops.get_image = get_image;
- rop3_init();
-}