summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorIzik Eidus <ieidus@redhat.com>2010-04-03 05:35:31 +0300
committerIzik Eidus <ieidus@redhat.com>2010-04-03 05:35:31 +0300
commit4a208b3644ab3a5e3e950400692303bf608f0129 (patch)
treebc728d5253346a71143e179f304c5b2398abaa3a /common
parent27a8ec1ef476a13734c33f01653af22cc0432800 (diff)
downloadspice-4a208b3644ab3a5e3e950400692303bf608f0129.tar.gz
spice-4a208b3644ab3a5e3e950400692303bf608f0129.tar.xz
spice-4a208b3644ab3a5e3e950400692303bf608f0129.zip
libspice: add off screens support
Signed-off-by: Izik Eidus <ieidus@redhat.com>
Diffstat (limited to 'common')
-rw-r--r--common/cairo_canvas.c402
-rw-r--r--common/cairo_canvas.h1
-rw-r--r--common/canvas_base.c530
-rw-r--r--common/canvas_base.h76
-rw-r--r--common/gdi_canvas.c465
-rw-r--r--common/gdi_canvas.h1
-rw-r--r--common/gl_canvas.c2
-rw-r--r--common/gl_canvas.h1
8 files changed, 1086 insertions, 392 deletions
diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c
index 770ca4ff..17a40a40 100644
--- a/common/cairo_canvas.c
+++ b/common/cairo_canvas.c
@@ -51,11 +51,18 @@ static pixman_image_t *canvas_get_pixman_brush(CairoCanvas *canvas,
return pixman_image_create_solid_fill(&c);
}
- case SPICE_BRUSH_TYPE_PATTERN: {
+ case SPICE_BRUSH_TYPE_PATTERN: {
+ CairoCanvas *surface_canvas;
pixman_image_t* surface;
pixman_transform_t t;
- surface = canvas_get_image(&canvas->base, brush->u.pattern.pat);
+ surface_canvas = (CairoCanvas *)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);
+ }
pixman_transform_init_translate(&t,
pixman_int_to_fixed(-brush->u.pattern.pos.x),
pixman_int_to_fixed(-brush->u.pattern.pos.y));
@@ -70,6 +77,14 @@ static pixman_image_t *canvas_get_pixman_brush(CairoCanvas *canvas,
}
}
+static pixman_image_t *get_image(SpiceCanvas *canvas)
+{
+ CairoCanvas *cairo_canvas = (CairoCanvas *)canvas;
+
+ pixman_image_ref(cairo_canvas->image);
+
+ return cairo_canvas->image;
+}
static void copy_region(SpiceCanvas *spice_canvas,
pixman_region32_t *dest_region,
@@ -194,16 +209,16 @@ static void fill_solid_rects_rop(SpiceCanvas *spice_canvas,
}
}
-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)
+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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
int i;
- for (i = 0; i < n_rects; 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,
@@ -212,17 +227,37 @@ static void fill_tiled_rects(SpiceCanvas *spice_canvas,
}
}
-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)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __fill_tiled_rects(spice_canvas, rects, n_rects, cairo_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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
int i;
- for (i = 0; i < n_rects; 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,
@@ -231,11 +266,32 @@ static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
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 blit_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __fill_tiled_rects_rop(spice_canvas, rects, n_rects, cairo_surface_canvas->image, offset_x,
+ offset_y, rop);
+}
+
+static void __blit_image(SpiceCanvas *spice_canvas,
+ pixman_region32_t *region,
+ pixman_image_t *src_image,
+ int offset_x, int offset_y)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_box32_t *rects;
@@ -262,11 +318,28 @@ static void blit_image(SpiceCanvas *spice_canvas,
}
}
-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)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __blit_image(spice_canvas, region, cairo_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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_box32_t *rects;
@@ -293,14 +366,35 @@ static void blit_image_rop(SpiceCanvas *spice_canvas,
}
}
-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)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __blit_image_rop(spice_canvas, region, cairo_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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_transform_t transform;
@@ -337,14 +431,41 @@ static void scale_image(SpiceCanvas *spice_canvas,
pixman_image_set_clip_region32(canvas->image, NULL);
}
-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)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __scale_image(spice_canvas, region, cairo_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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_transform_t transform;
@@ -407,13 +528,40 @@ static void scale_image_rop(SpiceCanvas *spice_canvas,
pixman_image_unref(scaled);
}
-static void blend_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __scale_image_rop(spice_canvas, region, cairo_surface_canvas->image, src_x, src_y, src_width,
+ src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop);
+}
+
+static void __blend_image(SpiceCanvas *spice_canvas,
+ pixman_region32_t *region,
+ pixman_image_t *src,
+ int src_x, int src_y,
+ int dest_x, int dest_y,
+ int width, int height,
+ int overall_alpha)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_image_t *mask;
@@ -444,15 +592,40 @@ static void blend_image(SpiceCanvas *spice_canvas,
pixman_image_set_clip_region32(canvas->image, NULL);
}
-static void blend_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,
- int overall_alpha)
+static void blend_image(SpiceCanvas *spice_canvas,
+ pixman_region32_t *region,
+ 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, 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,
+ SpiceCanvas *surface_canvas,
+ int src_x, int src_y,
+ int dest_x, int dest_y,
+ int width, int height,
+ int overall_alpha)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __blend_image(spice_canvas, region, cairo_surface_canvas->image, src_x, src_y, dest_x, dest_y,
+ width, height, overall_alpha);
+}
+
+static void __blend_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,
+ int overall_alpha)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_transform_t transform;
@@ -501,11 +674,41 @@ static void blend_scale_image(SpiceCanvas *spice_canvas,
pixman_image_set_clip_region32(canvas->image, NULL);
}
-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)
+static void blend_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,
+ int overall_alpha)
+{
+ __blend_scale_image(spice_canvas, region, 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,
+ 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,
+ int overall_alpha)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __blend_scale_image(spice_canvas, region, cairo_surface_canvas->image, src_x, src_y, src_width,
+ src_height, dest_x, dest_y, dest_width, dest_height, scale_mode,
+ overall_alpha);
+}
+
+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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_box32_t *rects;
@@ -533,14 +736,34 @@ static void colorkey_image(SpiceCanvas *spice_canvas,
}
}
-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)
+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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __colorkey_image(spice_canvas, region, cairo_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)
{
CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
pixman_transform_t transform;
@@ -600,6 +823,34 @@ static void colorkey_scale_image(SpiceCanvas *spice_canvas,
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)
+{
+ CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
+ __colorkey_scale_image(spice_canvas, region, cairo_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,
@@ -803,6 +1054,7 @@ SpiceCanvas *canvas_create(pixman_image_t *image, int bits
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, SpiceImageCache *bits_cache
#endif
+ , SpiceImageSurfaces *surfaces
, SpiceGlzDecoder *glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
@@ -826,6 +1078,7 @@ SpiceCanvas *canvas_create(pixman_image_t *image, int bits
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, bits_cache
#endif
+ , surfaces
, glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, virt_mapping
@@ -858,15 +1111,26 @@ void cairo_canvas_init() //unsafe global function
cairo_canvas_ops.fill_solid_rects = fill_solid_rects;
cairo_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop;
cairo_canvas_ops.fill_tiled_rects = fill_tiled_rects;
+ cairo_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface;
cairo_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop;
+ cairo_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface;
cairo_canvas_ops.blit_image = blit_image;
+ cairo_canvas_ops.blit_image_from_surface = blit_image_from_surface;
cairo_canvas_ops.blit_image_rop = blit_image_rop;
+ cairo_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface;
cairo_canvas_ops.scale_image = scale_image;
+ cairo_canvas_ops.scale_image_from_surface = scale_image_from_surface;
cairo_canvas_ops.scale_image_rop = scale_image_rop;
+ cairo_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface;
cairo_canvas_ops.blend_image = blend_image;
+ cairo_canvas_ops.blend_image_from_surface = blend_image_from_surface;
cairo_canvas_ops.blend_scale_image = blend_scale_image;
+ cairo_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface;
cairo_canvas_ops.colorkey_image = colorkey_image;
+ cairo_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface;
cairo_canvas_ops.colorkey_scale_image = colorkey_scale_image;
+ cairo_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface;
cairo_canvas_ops.copy_region = copy_region;
+ cairo_canvas_ops.get_image = get_image;
rop3_init();
}
diff --git a/common/cairo_canvas.h b/common/cairo_canvas.h
index 3f6fbbc6..e65b4076 100644
--- a/common/cairo_canvas.h
+++ b/common/cairo_canvas.h
@@ -33,6 +33,7 @@ SpiceCanvas *canvas_create(pixman_image_t *image, int bits
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, SpiceImageCache *bits_cache
#endif
+ , SpiceImageSurfaces *surfaces
, SpiceGlzDecoder *glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
diff --git a/common/canvas_base.c b/common/canvas_base.c
index e13a005b..e15a971a 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -190,6 +190,8 @@ typedef struct CanvasBase {
HDC dc;
#endif
+ SpiceImageSurfaces *surfaces;
+
LzData lz_data;
GlzData glz_data;
@@ -948,6 +950,34 @@ static void dump_surface(pixman_image_t *surface, int cache)
#endif
+static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SPICE_ADDRESS addr)
+{
+ SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
+ access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
+
+ if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) {
+ SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor;
+ access_test(canvas, descriptor, sizeof(SpiceSurfaceImage));
+ return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id);
+ }
+ return NULL;
+}
+
+static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SPICE_ADDRESS addr)
+{
+ SpiceImageDescriptor *descriptor;
+
+ descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
+ access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
+
+ if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) {
+ SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor;
+ access_test(canvas, descriptor, sizeof(SpiceSurfaceImage));
+ return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id);
+ }
+ return NULL;
+}
+
#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
//#define DEBUG_LZ
@@ -1065,6 +1095,16 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
#endif
+static SpiceCanvas *canvas_get_surface_mask(CanvasBase *canvas, SPICE_ADDRESS addr)
+{
+ return canvas_get_surface_mask_internal(canvas, addr);
+}
+
+static SpiceCanvas *canvas_get_surface(CanvasBase *canvas, SPICE_ADDRESS addr)
+{
+ return canvas_get_surface_internal(canvas, addr);
+}
+
static pixman_image_t *canvas_get_image(CanvasBase *canvas, SPICE_ADDRESS addr)
{
return canvas_get_image_internal(canvas, addr, TRUE);
@@ -1318,10 +1358,6 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
*needs_invert_out = 0;
}
- if (!mask->bitmap) {
- return NULL;
- }
-
descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(mask->bitmap);
access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS;
@@ -1807,6 +1843,7 @@ static void canvas_mask_pixman(CanvasBase *canvas,
pixman_region32_t *dest_region,
SpiceQMask *mask, int x, int y)
{
+ SpiceCanvas *surface_canvas;
pixman_image_t *image, *subimage;
int needs_invert;
pixman_region32_t mask_region;
@@ -1815,13 +1852,19 @@ static void canvas_mask_pixman(CanvasBase *canvas,
int mask_width, mask_height, mask_stride;
pixman_box32_t extents;
- needs_invert = FALSE;
- image = canvas_get_mask(canvas,
- mask,
- &needs_invert);
+ if (!mask->bitmap) {
+ return;
+ }
- if (image == NULL) {
- return; /* no mask */
+ surface_canvas = canvas_get_surface_mask(canvas, mask->bitmap);
+ if (surface_canvas) {
+ needs_invert = mask->flags & SPICE_MASK_FLAGS_INVERS;
+ image = surface_canvas->ops->get_image(surface_canvas);
+ } else {
+ needs_invert = FALSE;
+ image = canvas_get_mask(canvas,
+ mask,
+ &needs_invert);
}
mask_data = pixman_image_get_data(image);
@@ -1921,20 +1964,35 @@ static void draw_brush(SpiceCanvas *canvas,
canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, color, rop);
}
break;
- case SPICE_BRUSH_TYPE_PATTERN:
+ case SPICE_BRUSH_TYPE_PATTERN: {
+ SpiceCanvas *surface_canvas;
+
pattern = &brush->u.pattern;
- tile = canvas_get_image(canvas_base, pattern->pat);
offset_x = pattern->pos.x;
offset_y = pattern->pos.y;
- if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_tiled_rects(canvas, rects, n_rects, tile, offset_x, offset_y);
+ surface_canvas = canvas_get_surface(canvas_base, pattern->pat);
+ if (surface_canvas) {
+ if (rop == SPICE_ROP_COPY) {
+ canvas->ops->fill_tiled_rects_from_surface(canvas, rects, n_rects, surface_canvas,
+ offset_x, offset_y);
+ } else {
+ canvas->ops->fill_tiled_rects_rop_from_surface(canvas, rects, n_rects,
+ surface_canvas, offset_x, offset_y,
+ rop);
+ }
} else {
- canvas->ops->fill_tiled_rects_rop(canvas, rects, n_rects,
- tile, offset_x, offset_y, rop);
+ tile = canvas_get_image(canvas_base, pattern->pat);
+ if (rop == SPICE_ROP_COPY) {
+ canvas->ops->fill_tiled_rects(canvas, rects, n_rects, tile, offset_x, offset_y);
+ } else {
+ canvas->ops->fill_tiled_rects_rop(canvas, rects, n_rects,
+ tile, offset_x, offset_y, rop);
+ }
+ pixman_image_unref(tile);
}
- pixman_image_unref(tile);
break;
+ }
case SPICE_BRUSH_TYPE_NONE:
/* Still need to do *something* here, because rop could be e.g invert dest */
canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, 0, rop);
@@ -1991,6 +2049,7 @@ static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceCl
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
pixman_region32_t dest_region;
+ SpiceCanvas *surface_canvas;
pixman_image_t *src_image;
SpiceROP rop;
@@ -2013,36 +2072,67 @@ static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceCl
return;
}
- src_image = canvas_get_image(canvas, copy->src_bitmap);
-
- if (rect_is_same_size(bbox, &copy->src_area)) {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->blit_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - copy->src_area.left,
- bbox->top - copy->src_area.top);
+ surface_canvas = canvas_get_surface(canvas, copy->src_bitmap);
+ if (surface_canvas) {
+ if (rect_is_same_size(bbox, &copy->src_area)) {
+ if (rop == SPICE_ROP_COPY) {
+ spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ bbox->left - copy->src_area.left,
+ bbox->top - copy->src_area.top);
+ } else {
+ spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ bbox->left - copy->src_area.left,
+ bbox->top - copy->src_area.top,
+ rop);
+ }
} else {
- spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region,
- src_image,
- bbox->left - copy->src_area.left,
- bbox->top - copy->src_area.top,
- rop);
+ if (rop == SPICE_ROP_COPY) {
+ spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ copy->src_area.left,
+ copy->src_area.top,
+ copy->src_area.right - copy->src_area.left,
+ copy->src_area.bottom - copy->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ copy->scale_mode);
+ } else {
+ spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ copy->src_area.left,
+ copy->src_area.top,
+ copy->src_area.right - copy->src_area.left,
+ copy->src_area.bottom - copy->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ copy->scale_mode,
+ rop);
+ }
}
} else {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->scale_image(spice_canvas, &dest_region,
- src_image,
- copy->src_area.left,
- copy->src_area.top,
- copy->src_area.right - copy->src_area.left,
- copy->src_area.bottom - copy->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- copy->scale_mode);
+ src_image = canvas_get_image(canvas, copy->src_bitmap);
+ if (rect_is_same_size(bbox, &copy->src_area)) {
+ if (rop == SPICE_ROP_COPY) {
+ spice_canvas->ops->blit_image(spice_canvas, &dest_region,
+ src_image,
+ bbox->left - copy->src_area.left,
+ bbox->top - copy->src_area.top);
+ } else {
+ spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region,
+ src_image,
+ bbox->left - copy->src_area.left,
+ bbox->top - copy->src_area.top,
+ rop);
+ }
} else {
- spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region,
+ if (rop == SPICE_ROP_COPY) {
+ spice_canvas->ops->scale_image(spice_canvas, &dest_region,
src_image,
copy->src_area.left,
copy->src_area.top,
@@ -2052,18 +2142,31 @@ static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceCl
bbox->top,
bbox->right - bbox->left,
bbox->bottom - bbox->top,
- copy->scale_mode,
- rop);
+ copy->scale_mode);
+ } else {
+ spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region,
+ src_image,
+ copy->src_area.left,
+ copy->src_area.top,
+ copy->src_area.right - copy->src_area.left,
+ copy->src_area.bottom - copy->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ copy->scale_mode,
+ rop);
+ }
}
+ pixman_image_unref(src_image);
}
-
- pixman_image_unref(src_image);
pixman_region32_fini(&dest_region);
}
static void canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent)
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
+ SpiceCanvas *surface_canvas;
pixman_image_t *src_image;
pixman_region32_t dest_region;
@@ -2080,29 +2183,50 @@ static void canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox,
return;
}
- src_image = canvas_get_image(canvas, transparent->src_bitmap);
-
- if (rect_is_same_size(bbox, &transparent->src_area)) {
- spice_canvas->ops->colorkey_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - transparent->src_area.left,
- bbox->top - transparent->src_area.top,
- transparent->true_color);
+ surface_canvas = canvas_get_surface(canvas, transparent->src_bitmap);
+ if (surface_canvas) {
+ if (rect_is_same_size(bbox, &transparent->src_area)) {
+ spice_canvas->ops->colorkey_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ bbox->left - transparent->src_area.left,
+ bbox->top - transparent->src_area.top,
+ transparent->true_color);
+ } else {
+ spice_canvas->ops->colorkey_scale_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ transparent->src_area.left,
+ transparent->src_area.top,
+ transparent->src_area.right - transparent->src_area.left,
+ transparent->src_area.bottom - transparent->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ transparent->true_color);
+ }
} else {
- spice_canvas->ops->colorkey_scale_image(spice_canvas, &dest_region,
- src_image,
- transparent->src_area.left,
- transparent->src_area.top,
- transparent->src_area.right - transparent->src_area.left,
- transparent->src_area.bottom - transparent->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- transparent->true_color);
+ src_image = canvas_get_image(canvas, transparent->src_bitmap);
+ if (rect_is_same_size(bbox, &transparent->src_area)) {
+ spice_canvas->ops->colorkey_image(spice_canvas, &dest_region,
+ src_image,
+ bbox->left - transparent->src_area.left,
+ bbox->top - transparent->src_area.top,
+ transparent->true_color);
+ } else {
+ spice_canvas->ops->colorkey_scale_image(spice_canvas, &dest_region,
+ src_image,
+ transparent->src_area.left,
+ transparent->src_area.top,
+ transparent->src_area.right - transparent->src_area.left,
+ transparent->src_area.bottom - transparent->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ transparent->true_color);
+ }
+ pixman_image_unref(src_image);
}
-
- pixman_image_unref(src_image);
pixman_region32_fini(&dest_region);
}
@@ -2110,6 +2234,7 @@ static void canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox,
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
pixman_region32_t dest_region;
+ SpiceCanvas *surface_canvas;
pixman_image_t *src_image;
pixman_region32_init_rect(&dest_region,
@@ -2126,34 +2251,62 @@ static void canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox,
return;
}
- src_image = canvas_get_image(canvas, alpha_blend->src_bitmap);
-
- if (rect_is_same_size(bbox, &alpha_blend->src_area)) {
- spice_canvas->ops->blend_image(spice_canvas, &dest_region,
- src_image,
- alpha_blend->src_area.left,
- alpha_blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- alpha_blend->alpha);
- } else {
- spice_canvas->ops->blend_scale_image(spice_canvas, &dest_region,
- src_image,
- alpha_blend->src_area.left,
- alpha_blend->src_area.top,
- alpha_blend->src_area.right - alpha_blend->src_area.left,
- alpha_blend->src_area.bottom - alpha_blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- SPICE_IMAGE_SCALE_MODE_NEAREST,
- alpha_blend->alpha);
+ surface_canvas = canvas_get_surface(canvas, alpha_blend->src_bitmap);
+ if (surface_canvas) {
+ if (rect_is_same_size(bbox, &alpha_blend->src_area)) {
+ spice_canvas->ops->blend_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ alpha_blend->src_area.left,
+ alpha_blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ alpha_blend->alpha);
+ } else {
+ spice_canvas->ops->blend_scale_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ alpha_blend->src_area.left,
+ alpha_blend->src_area.top,
+ alpha_blend->src_area.right - alpha_blend->src_area.left,
+ alpha_blend->src_area.bottom - alpha_blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ SPICE_IMAGE_SCALE_MODE_NEAREST,
+ alpha_blend->alpha);
+ }
+ } else {
+ src_image = canvas_get_image(canvas, alpha_blend->src_bitmap);
+ if (rect_is_same_size(bbox, &alpha_blend->src_area)) {
+ spice_canvas->ops->blend_image(spice_canvas, &dest_region,
+ src_image,
+ alpha_blend->src_area.left,
+ alpha_blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ alpha_blend->alpha);
+ } else {
+ spice_canvas->ops->blend_scale_image(spice_canvas, &dest_region,
+ src_image,
+ alpha_blend->src_area.left,
+ alpha_blend->src_area.top,
+ alpha_blend->src_area.right - alpha_blend->src_area.left,
+ alpha_blend->src_area.bottom - alpha_blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ SPICE_IMAGE_SCALE_MODE_NEAREST,
+ alpha_blend->alpha);
+ }
+
+ pixman_image_unref(src_image);
}
- pixman_image_unref(src_image);
pixman_region32_fini(&dest_region);
}
@@ -2214,6 +2367,7 @@ static void canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spice
static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend)
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
+ SpiceCanvas *surface_canvas;
pixman_image_t *src_image;
pixman_region32_t dest_region;
SpiceROP rop;
@@ -2237,40 +2391,74 @@ static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceC
return;
}
- src_image = canvas_get_image(canvas, blend->src_bitmap);
-
- if (rect_is_same_size(bbox, &blend->src_area)) {
- if (rop == SPICE_ROP_COPY)
- spice_canvas->ops->blit_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - blend->src_area.left,
- bbox->top - blend->src_area.top);
- else
- spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region,
+ surface_canvas = canvas_get_surface(canvas, blend->src_bitmap);
+ if (surface_canvas) {
+ if (rect_is_same_size(bbox, &blend->src_area)) {
+ if (rop == SPICE_ROP_COPY)
+ spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ bbox->left - blend->src_area.left,
+ bbox->top - blend->src_area.top);
+ else
+ spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ bbox->left - blend->src_area.left,
+ bbox->top - blend->src_area.top,
+ rop);
+ } else {
+ double sx, sy;
+
+ sx = (double)(blend->src_area.right - blend->src_area.left) / (bbox->right - bbox->left);
+ sy = (double)(blend->src_area.bottom - blend->src_area.top) / (bbox->bottom - bbox->top);
+
+ if (rop == SPICE_ROP_COPY) {
+ spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ blend->src_area.left,
+ blend->src_area.top,
+ blend->src_area.right - blend->src_area.left,
+ blend->src_area.bottom - blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ blend->scale_mode);
+ } else {
+ spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region,
+ surface_canvas,
+ blend->src_area.left,
+ blend->src_area.top,
+ blend->src_area.right - blend->src_area.left,
+ blend->src_area.bottom - blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ blend->scale_mode, rop);
+ }
+ }
+ } else {
+ src_image = canvas_get_image(canvas, blend->src_bitmap);
+ if (rect_is_same_size(bbox, &blend->src_area)) {
+ if (rop == SPICE_ROP_COPY)
+ spice_canvas->ops->blit_image(spice_canvas, &dest_region,
src_image,
bbox->left - blend->src_area.left,
- bbox->top - blend->src_area.top,
- rop);
- } else {
- double sx, sy;
-
- sx = (double)(blend->src_area.right - blend->src_area.left) / (bbox->right - bbox->left);
- sy = (double)(blend->src_area.bottom - blend->src_area.top) / (bbox->bottom - bbox->top);
-
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->scale_image(spice_canvas, &dest_region,
- src_image,
- blend->src_area.left,
- blend->src_area.top,
- blend->src_area.right - blend->src_area.left,
- blend->src_area.bottom - blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- blend->scale_mode);
+ bbox->top - blend->src_area.top);
+ else
+ spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region,
+ src_image,
+ bbox->left - blend->src_area.left,
+ bbox->top - blend->src_area.top,
+ rop);
} else {
- spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region,
+ double sx, sy;
+
+ sx = (double)(blend->src_area.right - blend->src_area.left) / (bbox->right - bbox->left);
+ sy = (double)(blend->src_area.bottom - blend->src_area.top) / (bbox->bottom - bbox->top);
+
+ if (rop == SPICE_ROP_COPY) {
+ spice_canvas->ops->scale_image(spice_canvas, &dest_region,
src_image,
blend->src_area.left,
blend->src_area.top,
@@ -2280,11 +2468,23 @@ static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceC
bbox->top,
bbox->right - bbox->left,
bbox->bottom - bbox->top,
- blend->scale_mode, rop);
+ blend->scale_mode);
+ } else {
+ spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region,
+ src_image,
+ blend->src_area.left,
+ blend->src_area.top,
+ blend->src_area.right - blend->src_area.left,
+ blend->src_area.bottom - blend->src_area.top,
+ bbox->left,
+ bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top,
+ blend->scale_mode, rop);
+ }
}
+ pixman_image_unref(src_image);
}
-
- pixman_image_unref(src_image);
pixman_region32_fini(&dest_region);
}
@@ -2382,7 +2582,11 @@ typedef struct {
SpiceROP back_rop;
int solid;
uint32_t color;
- pixman_image_t *tile;
+ int use_surface_canvas;
+ union {
+ SpiceCanvas *surface_canvas;
+ pixman_image_t *tile;
+ };
int tile_offset_x;
int tile_offset_y;
} StrokeGC;
@@ -2505,16 +2709,31 @@ static void stroke_fill_rects(lineGC * pGC,
}
} else {
if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_tiled_rects(canvas, area_rects, n_area_rects,
- strokeGC->tile,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y);
- } else {
- canvas->ops->fill_tiled_rects_rop(canvas, area_rects, n_area_rects,
+ if (strokeGC->use_surface_canvas) {
+ canvas->ops->fill_tiled_rects_from_surface(canvas, area_rects, n_area_rects,
+ strokeGC->surface_canvas,
+ strokeGC->tile_offset_x,
+ strokeGC->tile_offset_y);
+ } else {
+ canvas->ops->fill_tiled_rects(canvas, area_rects, n_area_rects,
strokeGC->tile,
strokeGC->tile_offset_x,
- strokeGC->tile_offset_y,
- rop);
+ strokeGC->tile_offset_y);
+ }
+ } else {
+ if (strokeGC->use_surface_canvas) {
+ canvas->ops->fill_tiled_rects_rop_from_surface(canvas, area_rects, n_area_rects,
+ strokeGC->surface_canvas,
+ strokeGC->tile_offset_x,
+ strokeGC->tile_offset_y,
+ rop);
+ } else {
+ canvas->ops->fill_tiled_rects_rop(canvas, area_rects, n_area_rects,
+ strokeGC->tile,
+ strokeGC->tile_offset_x,
+ strokeGC->tile_offset_y,
+ rop);
+ }
}
}
@@ -2661,6 +2880,7 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
SpiceClip *clip, SpiceStroke *stroke)
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
+ SpiceCanvas *surface_canvas = NULL;
StrokeGC gc = { { 0 } };
lineGCOps ops = {
stroke_fill_spans,
@@ -2754,8 +2974,16 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
break;
case SPICE_BRUSH_TYPE_PATTERN:
gc.solid = FALSE;
- gc.tile = canvas_get_image(canvas,
- stroke->brush.u.pattern.pat);
+ surface_canvas = canvas_get_surface(canvas,
+ stroke->brush.u.pattern.pat);
+ if (surface_canvas) {
+ gc.use_surface_canvas = TRUE;
+ gc.surface_canvas = surface_canvas;
+ } else {
+ gc.use_surface_canvas = FALSE;
+ gc.tile = canvas_get_image(canvas,
+ stroke->brush.u.pattern.pat);
+ }
gc.tile_offset_x = stroke->brush.u.pattern.pos.x;
gc.tile_offset_y = stroke->brush.u.pattern.pos.y;
break;
@@ -2817,17 +3045,20 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
}
stroke_lines_free(&lines);
- if (!gc.solid && gc.tile) {
+ if (!gc.solid && gc.tile && !surface_canvas) {
pixman_image_unref(gc.tile);
}
pixman_region32_fini(&gc.dest_region);
}
+
+//need surfaces handling here !!!
static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
SpiceClip *clip, SpiceRop3 *rop3)
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
+ SpiceCanvas *surface_canvas;
pixman_region32_t dest_region;
pixman_image_t *d;
pixman_image_t *s;
@@ -2848,7 +3079,12 @@ static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
heigth = bbox->bottom - bbox->top;
d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, heigth);
- s = canvas_get_image(canvas, rop3->src_bitmap);
+ surface_canvas = canvas_get_surface(canvas, rop3->src_bitmap);
+ if (surface_canvas) {
+ s = surface_canvas->ops->get_image(surface_canvas);
+ } else {
+ s = canvas_get_image(canvas, rop3->src_bitmap);
+ }
if (!rect_is_same_size(bbox, &rop3->src_area)) {
pixman_image_t *scaled_s = canvas_scale_surface(s, &rop3->src_area, width, heigth,
@@ -2866,7 +3102,15 @@ static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
CANVAS_ERROR("bad src bitmap size");
}
if (rop3->brush.type == SPICE_BRUSH_TYPE_PATTERN) {
- pixman_image_t *p = canvas_get_image(canvas, rop3->brush.u.pattern.pat);
+ SpiceCanvas *_surface_canvas;
+ pixman_image_t *p;
+
+ _surface_canvas = canvas_get_surface(canvas, rop3->brush.u.pattern.pat);
+ if (_surface_canvas) {
+ p = _surface_canvas->ops->get_image(_surface_canvas);
+ } else {
+ p = canvas_get_image(canvas, rop3->brush.u.pattern.pat);
+ }
SpicePoint pat_pos;
pat_pos.x = (bbox->left - rop3->brush.u.pattern.pos.x) % pixman_image_get_width(p);
@@ -2988,6 +3232,7 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, SpiceImageCache *bits_cache
#endif
+ , SpiceImageSurfaces *surfaces
, SpiceGlzDecoder *glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
@@ -3020,6 +3265,7 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
return 0;
}
#endif
+ canvas->surfaces = surfaces;
canvas->glz_data.decoder = glz_decoder;
if (depth == 16) {
diff --git a/common/canvas_base.h b/common/canvas_base.h
index bed1e1ba..0a663bd1 100644
--- a/common/canvas_base.h
+++ b/common/canvas_base.h
@@ -28,6 +28,7 @@
typedef void (*spice_destroy_fn_t)(void *data);
typedef struct _SpiceImageCache SpiceImageCache;
+typedef struct _SpiceImageSurfaces SpiceImageSurfaces;
typedef struct _SpicePaletteCache SpicePaletteCache;
typedef struct _SpiceGlzDecoder SpiceGlzDecoder;
typedef struct _SpiceVirtMapping SpiceVirtMapping;
@@ -46,6 +47,15 @@ struct _SpiceImageCache {
};
typedef struct {
+ SpiceCanvas *(*get)(SpiceImageSurfaces *surfaces,
+ uint32_t surface_id);
+} SpiceImageSurfacesOps;
+
+struct _SpiceImageSurfaces {
+ SpiceImageSurfacesOps *ops;
+};
+
+typedef struct {
void (*put)(SpicePaletteCache *cache,
SpicePalette *palette);
SpicePalette *(*get)(SpicePaletteCache *cache,
@@ -127,21 +137,41 @@ typedef struct {
int n_rects,
pixman_image_t *tile,
int offset_x, int offset_y);
+ void (*fill_tiled_rects_from_surface)(SpiceCanvas *canvas,
+ pixman_box32_t *rects,
+ int n_rects,
+ SpiceCanvas *tile,
+ int offset_x, int offset_y);
void (*fill_tiled_rects_rop)(SpiceCanvas *canvas,
pixman_box32_t *rects,
int n_rects,
pixman_image_t *tile,
int offset_x, int offset_y,
SpiceROP rop);
+ void (*fill_tiled_rects_rop_from_surface)(SpiceCanvas *canvas,
+ pixman_box32_t *rects,
+ int n_rects,
+ SpiceCanvas *tile,
+ int offset_x, int offset_y,
+ SpiceROP rop);
void (*blit_image)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
int offset_x, int offset_y);
+ void (*blit_image_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ int offset_x, int offset_y);
void (*blit_image_rop)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
int offset_x, int offset_y,
SpiceROP rop);
+ void (*blit_image_rop_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ int offset_x, int offset_y,
+ SpiceROP rop);
void (*scale_image)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
@@ -150,6 +180,14 @@ typedef struct {
int dest_x, int dest_y,
int dest_width, int dest_height,
int scale_mode);
+ void (*scale_image_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ 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);
void (*scale_image_rop)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
@@ -158,6 +196,14 @@ typedef struct {
int dest_x, int dest_y,
int dest_width, int dest_height,
int scale_mode, SpiceROP rop);
+ void (*scale_image_rop_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ 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);
void (*blend_image)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
@@ -165,6 +211,13 @@ typedef struct {
int dest_x, int dest_y,
int width, int height,
int overall_alpha);
+ void (*blend_image_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ int src_x, int src_y,
+ int dest_x, int dest_y,
+ int width, int height,
+ int overall_alpha);
void (*blend_scale_image)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
@@ -174,11 +227,25 @@ typedef struct {
int dest_width, int dest_height,
int scale_mode,
int overall_alpha);
+ void (*blend_scale_image_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ 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);
void (*colorkey_image)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
int offset_x, int offset_y,
uint32_t transparent_color);
+ void (*colorkey_image_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ int offset_x, int offset_y,
+ uint32_t transparent_color);
void (*colorkey_scale_image)(SpiceCanvas *canvas,
pixman_region32_t *region,
pixman_image_t *src_image,
@@ -187,9 +254,18 @@ typedef struct {
int dest_x, int dest_y,
int dest_width, int dest_height,
uint32_t transparent_color);
+ void (*colorkey_scale_image_from_surface)(SpiceCanvas *canvas,
+ pixman_region32_t *region,
+ SpiceCanvas *src_image,
+ 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);
void (*copy_region)(SpiceCanvas *canvas,
pixman_region32_t *dest_region,
int dx, int dy);
+ pixman_image_t *(*get_image)(SpiceCanvas *canvas);
} SpiceCanvasOps;
void spice_canvas_set_usr_data(SpiceCanvas *canvas, void *data, spice_destroy_fn_t destroy_fn);
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
index 5eb31fe7..75dff69a 100644
--- a/common/gdi_canvas.c
+++ b/common/gdi_canvas.c
@@ -42,6 +42,7 @@ struct BitmapData {
uint8_t flags;
HDC dc;
int cache;
+ int from_surface;
};
#define _rop3_brush 0xf0
@@ -644,7 +645,8 @@ static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush)
CANVAS_ERROR("CreateSolidBrush failed");
}
return hbrush;
- case SPICE_BRUSH_TYPE_PATTERN: {
+ case SPICE_BRUSH_TYPE_PATTERN: {
+ GdiCanvas *gdi_surface = NULL;
GdiImage image;
HBRUSH hbrush;
pixman_image_t *surface;
@@ -652,21 +654,31 @@ static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush)
HBITMAP bitmap;
HBITMAP prev_bitmap;
- surface = canvas_get_image(&canvas->base, brush->u.pattern.pat);
- surface_to_image(surface, &image);
-
- if (!create_bitmap(&bitmap, &prev_bitmap, &dc, image.pixels, image.width,
- image.height, image.stride, 32, 0)) {
- CANVAS_ERROR("create_bitmap failed");
- return NULL;
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat);
+ if (gdi_surface) {
+ bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP);
+ if (!bitmap) {
+ CANVAS_ERROR("GetCurrentObject failed");
+ }
+ } else {
+ surface = canvas_get_image(&canvas->base, brush->u.pattern.pat);
+ surface_to_image(surface, &image);
+
+ if (!create_bitmap(&bitmap, &prev_bitmap, &dc, image.pixels, image.width,
+ image.height, image.stride, 32, 0)) {
+ CANVAS_ERROR("create_bitmap failed");
+ return NULL;
+ }
}
if (!(hbrush = CreatePatternBrush(bitmap))) {
CANVAS_ERROR("CreatePatternBrush failed");
}
- release_bitmap(dc, bitmap, prev_bitmap, 0);
- pixman_image_unref(surface);
+ if (!gdi_surface) {
+ release_bitmap(dc, bitmap, prev_bitmap, 0);
+ pixman_image_unref(surface);
+ }
return hbrush;
}
case SPICE_BRUSH_TYPE_NONE:
@@ -781,30 +793,53 @@ uint8_t calc_rop3_src_brush(uint16_t rop3_bits)
static struct BitmapData get_mask_bitmap(struct GdiCanvas *canvas, struct SpiceQMask *mask)
{
+ GdiCanvas *gdi_surface;
pixman_image_t *surface;
struct BitmapData bitmap;
PixmanData *pixman_data;
bitmap.hbitmap = NULL;
- if (!(surface = canvas_get_mask(&canvas->base, mask, NULL))) {
+ if (!mask->bitmap) {
return bitmap;
}
- pixman_data = (PixmanData *)pixman_image_get_destroy_data (surface);
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- bitmap.dc = create_compatible_dc();
- bitmap.prev_hbitmap = (HBITMAP)SelectObject(bitmap.dc, pixman_data->bitmap);
- bitmap.hbitmap = pixman_data->bitmap;
- ReleaseMutex(pixman_data->mutex);
- bitmap.cache = 1;
- } else if (!create_bitmap(&bitmap.hbitmap, &bitmap.prev_hbitmap, &bitmap.dc,
- (uint8_t *)pixman_image_get_data(surface),
- pixman_image_get_width(surface),
- pixman_image_get_height(surface),
- pixman_image_get_stride(surface), 1, 0)) {
- bitmap.hbitmap = NULL;
+ gdi_surface = (GdiCanvas *)canvas_get_surface_mask(&canvas->base, mask->bitmap);
+ if (gdi_surface) {
+ HBITMAP _bitmap;
+
+ _bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP);
+ if (!_bitmap) {
+ CANVAS_ERROR ("GetCurrentObject failed");
+ }
+ bitmap.dc = gdi_surface->dc;
+ bitmap.hbitmap = _bitmap;
+ bitmap.prev_hbitmap = (HBITMAP)0;
+ bitmap.cache = 0;
+ bitmap.from_surface = 1;
} else {
- bitmap.cache = 0;
+
+ if (!(surface = canvas_get_mask(&canvas->base, mask, NULL))) {
+ return bitmap;
+ }
+
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data (surface);
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ bitmap.dc = create_compatible_dc();
+ bitmap.prev_hbitmap = (HBITMAP)SelectObject(bitmap.dc, pixman_data->bitmap);
+ bitmap.hbitmap = pixman_data->bitmap;
+ ReleaseMutex(pixman_data->mutex);
+ bitmap.cache = 1;
+ } else if (!create_bitmap(&bitmap.hbitmap, &bitmap.prev_hbitmap, &bitmap.dc,
+ (uint8_t *)pixman_image_get_data(surface),
+ pixman_image_get_width(surface),
+ pixman_image_get_height(surface),
+ pixman_image_get_stride(surface), 1, 0)) {
+ bitmap.hbitmap = NULL;
+ } else {
+ bitmap.cache = 0;
+ }
+
+ bitmap.from_surface = 0;
}
bitmap.flags = mask->flags;
@@ -859,7 +894,9 @@ static void gdi_draw_bitmap_redrop(HDC dest_dc, const SpiceRect *src, const Spic
static void free_mask(struct BitmapData *bitmap)
{
if (bitmap->hbitmap) {
- release_bitmap(bitmap->dc, bitmap->hbitmap, bitmap->prev_hbitmap, bitmap->cache);
+ if (!bitmap->from_surface) {
+ release_bitmap(bitmap->dc, bitmap->hbitmap, bitmap->prev_hbitmap, bitmap->cache);
+ }
}
}
@@ -985,13 +1022,15 @@ static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi
HBRUSH brush;
struct BitmapData bitmapmask;
+ Lock lock(*canvas->lock);
+
if (!(brush = get_brush(canvas, &fill->brush))) {
CANVAS_ERROR("no braash");
return;
}
+
bitmapmask = get_mask_bitmap(canvas, &fill->mask);
- Lock lock(*canvas->lock);
set_clip(canvas, clip);
prev_hbrush = set_brush(canvas->dc, brush, &fill->brush);
gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask,
@@ -1004,40 +1043,51 @@ static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi
static void gdi_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy)
{
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
+ GdiCanvas *gdi_surface;
pixman_image_t *surface;
GdiImage image;
struct BitmapData bitmapmask;
PixmanData *pixman_data;
- bitmapmask = get_mask_bitmap(canvas, &copy->mask);
- surface = canvas_get_image(&canvas->base, copy->src_bitmap);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- Lock lock(*canvas->lock);
- set_scale_mode(canvas, copy->scale_mode);
- set_clip(canvas, clip);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_redrop(canvas->dc, &copy->src_area, bbox, dc,
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, copy->src_bitmap);
+ if (gdi_surface) {
+ Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &copy->mask);
+ set_scale_mode(canvas, copy->scale_mode);
+ set_clip(canvas, clip);
+ gdi_draw_bitmap_redrop(canvas->dc, &copy->src_area, bbox, gdi_surface->dc,
&bitmapmask, copy->rop_decriptor, 0);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
} else {
- surface_to_image(surface, &image);
- gdi_draw_image(canvas->dc, &copy->src_area, bbox, image.pixels,
- image.stride, image.width, image.height, &bitmapmask,
- copy->rop_decriptor, 0);
- }
+ surface = canvas_get_image(&canvas->base, copy->src_bitmap);
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
+
+ Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &copy->mask);
+ set_scale_mode(canvas, copy->scale_mode);
+ set_clip(canvas, clip);
+
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ HDC dc;
+ HBITMAP prev_bitmap;
+
+ dc = create_compatible_dc();
+ prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
+ gdi_draw_bitmap_redrop(canvas->dc, &copy->src_area, bbox, dc,
+ &bitmapmask, copy->rop_decriptor, 0);
+ SelectObject(dc, prev_bitmap);
+ DeleteObject(dc);
+ ReleaseMutex(pixman_data->mutex);
+ } else {
+ surface_to_image(surface, &image);
+ gdi_draw_image(canvas->dc, &copy->src_area, bbox, image.pixels,
+ image.stride, image.width, image.height, &bitmapmask,
+ copy->rop_decriptor, 0);
+ }
+ pixman_image_unref(surface);
+
+ }
free_mask(&bitmapmask);
-
- pixman_image_unref(surface);
}
static void gdi_canvas_put_image(SpiceCanvas *spice_canvas, HDC dc, const SpiceRect *dest, const uint8_t *src_data,
@@ -1136,34 +1186,43 @@ static void gdi_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bb
SpiceTransparent* transparent)
{
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
+ GdiCanvas *gdi_surface;
pixman_image_t *surface;
GdiImage image;
PixmanData *pixman_data;
- surface = canvas_get_image(&canvas->base, transparent->src_bitmap);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
- Lock lock(*canvas->lock);
- set_clip(canvas, clip);
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, dc,
- transparent->true_color);
-
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, transparent->src_bitmap);
+ if (gdi_surface) {
+ Lock lock(*canvas->lock);
+ set_clip(canvas, clip);
+ gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox,
+ gdi_surface->dc, transparent->true_color);
} else {
- surface_to_image(surface, &image);
- gdi_draw_image_transparent(canvas, canvas->dc, &transparent->src_area, bbox, image.pixels,
- image.stride, image.width, image.height,
- transparent->true_color, 0);
+ surface = canvas_get_image(&canvas->base, transparent->src_bitmap);
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
+ Lock lock(*canvas->lock);
+ set_clip(canvas, clip);
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ HDC dc;
+ HBITMAP prev_bitmap;
+
+ dc = create_compatible_dc();
+ prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
+ gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, dc,
+ transparent->true_color);
+
+ SelectObject(dc, prev_bitmap);
+ DeleteObject(dc);
+ ReleaseMutex(pixman_data->mutex);
+ } else {
+ surface_to_image(surface, &image);
+ gdi_draw_image_transparent(canvas, canvas->dc, &transparent->src_area, bbox, image.pixels,
+ image.stride, image.width, image.height,
+ transparent->true_color, 0);
+ }
+
+ pixman_image_unref(surface);
}
-
- pixman_image_unref(surface);
}
static void gdi_draw_bitmap_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
@@ -1208,40 +1267,51 @@ static void gdi_draw_image_alpha(HDC dest_dc, const SpiceRect *src, const SpiceR
static void gdi_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlnd* alpha_blend)
{
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
+ GdiCanvas *gdi_surface;
pixman_image_t *surface;
GdiImage image;
PixmanData *pixman_data;
int use_bitmap_alpha;
- surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap);
- use_bitmap_alpha = pixman_image_get_depth(surface) == 32;
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- Lock lock(*canvas->lock);
- set_clip(canvas, clip);
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, dc, alpha_blend->alpha,
- use_bitmap_alpha);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, alpha_blend->src_bitmap);
+ if (gdi_surface) {
+ Lock lock(*canvas->lock);
+ set_clip(canvas, clip);
+ use_bitmap_alpha = 0;
+ gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, gdi_surface->dc,
+ alpha_blend->alpha, use_bitmap_alpha);
} else {
- surface_to_image(surface, &image);
- gdi_draw_image_alpha(canvas->dc, &alpha_blend->src_area, bbox, image.pixels,
- image.stride, image.width, image.height,
- alpha_blend->alpha, 0, use_bitmap_alpha);
+ surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap);
+ use_bitmap_alpha = pixman_image_get_depth(surface) == 32;
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
+
+ Lock lock(*canvas->lock);
+ set_clip(canvas, clip);
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ HDC dc;
+ HBITMAP prev_bitmap;
+
+ dc = create_compatible_dc();
+ prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
+ gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, dc, alpha_blend->alpha,
+ use_bitmap_alpha);
+ SelectObject(dc, prev_bitmap);
+ DeleteObject(dc);
+ ReleaseMutex(pixman_data->mutex);
+ } else {
+ surface_to_image(surface, &image);
+ gdi_draw_image_alpha(canvas->dc, &alpha_blend->src_area, bbox, image.pixels,
+ image.stride, image.width, image.height,
+ alpha_blend->alpha, 0, use_bitmap_alpha);
+ }
+
+ pixman_image_unref(surface);
}
-
- pixman_image_unref(surface);
}
static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque)
{
+ GdiCanvas *gdi_surface;
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
pixman_image_t *surface;
GdiImage image;
@@ -1251,77 +1321,98 @@ static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, S
HBRUSH hbrush;
uint8_t rop3;
- surface = canvas_get_image(&canvas->base, opaque->src_bitmap);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
- bitmapmask = get_mask_bitmap(canvas, &opaque->mask);
rop3 = calc_rop3_src_brush(opaque->rop_decriptor);
- hbrush = get_brush(canvas, &opaque->brush);
-
- Lock lock(*canvas->lock);
- set_scale_mode(canvas, opaque->scale_mode);
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, opaque->src_bitmap);
+ if (gdi_surface) {
+ Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &opaque->mask);
+ hbrush = get_brush(canvas, &opaque->brush);
+ set_scale_mode(canvas, opaque->scale_mode);
+ set_clip(canvas, clip);
+ prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush);
+ gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3);
+ unset_brush(canvas->dc, prev_hbrush);
} else {
- surface_to_image(surface, &image);
- gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, image.pixels,
- image.stride, image.width, image.height, &bitmapmask, rop3, 0);
+ surface = canvas_get_image(&canvas->base, opaque->src_bitmap);
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
+
+ Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &opaque->mask);
+ hbrush = get_brush(canvas, &opaque->brush);
+ set_scale_mode(canvas, opaque->scale_mode);
+ set_clip(canvas, clip);
+ prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush);
+
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ HDC dc;
+ HBITMAP prev_bitmap;
+
+ dc = create_compatible_dc();
+ prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
+ gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3);
+ SelectObject(dc, prev_bitmap);
+ DeleteObject(dc);
+ ReleaseMutex(pixman_data->mutex);
+ } else {
+ surface_to_image(surface, &image);
+ gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, image.pixels,
+ image.stride, image.width, image.height, &bitmapmask, rop3, 0);
+ }
+ unset_brush(canvas->dc, prev_hbrush);
+ pixman_image_unref(surface);
}
- unset_brush(canvas->dc, prev_hbrush);
-
free_mask(&bitmapmask);
-
- pixman_image_unref(surface);
}
static void gdi_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend)
{
+ GdiCanvas *gdi_surface;
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
pixman_image_t *surface;
GdiImage image;
struct BitmapData bitmapmask;
PixmanData *pixman_data;
- bitmapmask = get_mask_bitmap(canvas, &blend->mask);
- surface = canvas_get_image(&canvas->base, blend->src_bitmap);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- Lock lock(*canvas->lock);
- set_scale_mode(canvas, blend->scale_mode);
- set_clip(canvas, clip);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, dc,
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, blend->src_bitmap);
+ if (gdi_surface) {
+ Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &blend->mask);
+ set_scale_mode(canvas, blend->scale_mode);
+ set_clip(canvas, clip);
+ gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, gdi_surface->dc,
&bitmapmask, blend->rop_decriptor, 0);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- surface_to_image(surface, &image);
- gdi_draw_image(canvas->dc, &blend->src_area, bbox, image.pixels, image.stride, image.width,
- image.height, &bitmapmask, blend->rop_decriptor, 0);
+ } else {
+ surface = canvas_get_image(&canvas->base, blend->src_bitmap);
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
+
+ Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &blend->mask);
+ set_scale_mode(canvas, blend->scale_mode);
+ set_clip(canvas, clip);
+
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ HDC dc;
+ HBITMAP prev_bitmap;
+
+ dc = create_compatible_dc();
+ prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
+ gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, dc,
+ &bitmapmask, blend->rop_decriptor, 0);
+ SelectObject(dc, prev_bitmap);
+ DeleteObject(dc);
+ ReleaseMutex(pixman_data->mutex);
+ } else {
+ surface_to_image(surface, &image);
+ gdi_draw_image(canvas->dc, &blend->src_area, bbox, image.pixels, image.stride, image.width,
+ image.height, &bitmapmask, blend->rop_decriptor, 0);
+ }
+
+ pixman_image_unref(surface);
}
free_mask(&bitmapmask);
-
- pixman_image_unref(surface);
}
static void gdi_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness)
@@ -1329,9 +1420,8 @@ static void gdi_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
struct BitmapData bitmapmask;
- bitmapmask = get_mask_bitmap(canvas, &blackness->mask);
-
Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &blackness->mask);
set_clip(canvas, clip);
gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x0);
@@ -1343,9 +1433,8 @@ static void gdi_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, S
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
struct BitmapData bitmapmask;
- bitmapmask = get_mask_bitmap(canvas, &invers->mask);
-
Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &invers->mask);
set_clip(canvas, clip);
gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x55);
@@ -1357,9 +1446,8 @@ static void gdi_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
struct BitmapData bitmapmask;
- bitmapmask = get_mask_bitmap(canvas, &whiteness->mask);
-
Lock lock(*canvas->lock);
+ bitmapmask = get_mask_bitmap(canvas, &whiteness->mask);
set_clip(canvas, clip);
gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0xff);
@@ -1368,6 +1456,7 @@ static void gdi_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox
static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3)
{
+ GdiCanvas *gdi_surface;
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
pixman_image_t *surface;
GdiImage image;
@@ -1376,37 +1465,49 @@ static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi
HBRUSH hbrush;
PixmanData *pixman_data;
- hbrush = get_brush(canvas, &rop3->brush);
- surface = canvas_get_image(&canvas->base, rop3->src_bitmap);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
- bitmapmask = get_mask_bitmap(canvas, &rop3->mask);
-
- Lock lock(*canvas->lock);
- set_scale_mode(canvas, rop3->scale_mode);
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc,
+ gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, rop3->src_bitmap);
+ if (gdi_surface) {
+ Lock lock(*canvas->lock);
+ hbrush = get_brush(canvas, &rop3->brush);
+ bitmapmask = get_mask_bitmap(canvas, &rop3->mask);
+ set_scale_mode(canvas, rop3->scale_mode);
+ set_clip(canvas, clip);
+ prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush);
+ gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc,
&bitmapmask, rop3->rop3);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
+ unset_brush(canvas->dc, prev_hbrush);
} else {
- surface_to_image(surface, &image);
- gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, image.pixels,
- image.stride, image.width, image.height, &bitmapmask, rop3->rop3, 0);
+ surface = canvas_get_image(&canvas->base, rop3->src_bitmap);
+ pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
+ Lock lock(*canvas->lock);
+ hbrush = get_brush(canvas, &rop3->brush);
+ bitmapmask = get_mask_bitmap(canvas, &rop3->mask);
+ set_scale_mode(canvas, rop3->scale_mode);
+ set_clip(canvas, clip);
+ prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush);
+
+ if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
+ HDC dc;
+ HBITMAP prev_bitmap;
+
+ dc = create_compatible_dc();
+ prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
+ gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc,
+ &bitmapmask, rop3->rop3);
+ SelectObject(dc, prev_bitmap);
+ DeleteObject(dc);
+ ReleaseMutex(pixman_data->mutex);
+ } else {
+ surface_to_image(surface, &image);
+ gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, image.pixels,
+ image.stride, image.width, image.height, &bitmapmask, rop3->rop3, 0);
+ }
+
+ unset_brush(canvas->dc, prev_hbrush);
+ pixman_image_unref(surface);
}
- unset_brush(canvas->dc, prev_hbrush);
free_mask(&bitmapmask);
-
- pixman_image_unref(surface);
}
static void gdi_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos)
@@ -1433,8 +1534,8 @@ static void gdi_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi
HBRUSH prev_hbrush;
HBRUSH hbrush;
- hbrush = get_brush(canvas, &text->back_brush);
Lock lock(*canvas->lock);
+ hbrush = get_brush(canvas, &text->back_brush);
prev_hbrush = set_brush(canvas->dc, hbrush, &text->back_brush);
gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL,
text->back_mode, 1);
@@ -1724,6 +1825,7 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, SpiceImageCache *bits_cache
#endif
+ , SpiceImageSurfaces *surfaces
, SpiceGlzDecoder *glz_decoder
)
{
@@ -1742,6 +1844,7 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, bits_cache
#endif
+ , surfaces
, glz_decoder);
canvas->dc = dc;
canvas->lock = lock;
diff --git a/common/gdi_canvas.h b/common/gdi_canvas.h
index 8b8f847d..73d6978e 100644
--- a/common/gdi_canvas.h
+++ b/common/gdi_canvas.h
@@ -37,6 +37,7 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
HDC dc, class Mutex *lock, int bits,
SpiceImageCache *bits_cache,
SpicePaletteCache *palette_cache,
+ SpiceImageSurfaces *surfaces,
SpiceGlzDecoder *glz_decoder);
void gdi_canvas_init();
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index f69c920b..3fd49f24 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -828,6 +828,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, int depth
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, SpiceImageCache *bits_cache
#endif
+ , SpiceImageSurfaces *surfaces
, SpiceGlzDecoder *glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
@@ -854,6 +855,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, int depth
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, bits_cache
#endif
+ , surfaces
, glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, virt_mapping
diff --git a/common/gl_canvas.h b/common/gl_canvas.h
index 29737ec8..6d236292 100644
--- a/common/gl_canvas.h
+++ b/common/gl_canvas.h
@@ -28,6 +28,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, int depth
#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
, SpiceImageCache *bits_cache
#endif
+ , SpiceImageSurfaces *surfaces
, SpiceGlzDecoder *glz_decoder
#ifndef CAIRO_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping