From 4a208b3644ab3a5e3e950400692303bf608f0129 Mon Sep 17 00:00:00 2001 From: Izik Eidus Date: Sat, 3 Apr 2010 05:35:31 +0300 Subject: libspice: add off screens support Signed-off-by: Izik Eidus --- common/cairo_canvas.c | 402 +++++++++++++++++++++++++++++++------- common/cairo_canvas.h | 1 + common/canvas_base.c | 530 ++++++++++++++++++++++++++++++++++++-------------- common/canvas_base.h | 76 ++++++++ common/gdi_canvas.c | 465 ++++++++++++++++++++++++++----------------- common/gdi_canvas.h | 1 + common/gl_canvas.c | 2 + common/gl_canvas.h | 1 + 8 files changed, 1086 insertions(+), 392 deletions(-) (limited to 'common') 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, ©->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, ©->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, ©->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; @@ -45,6 +46,15 @@ struct _SpiceImageCache { SpiceImageCacheOps *ops; }; +typedef struct { + SpiceCanvas *(*get)(SpiceImageSurfaces *surfaces, + uint32_t surface_id); +} SpiceImageSurfacesOps; + +struct _SpiceImageSurfaces { + SpiceImageSurfacesOps *ops; +}; + typedef struct { void (*put)(SpicePaletteCache *cache, SpicePalette *palette); @@ -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, ©->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, ©->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, ©->mask); + set_scale_mode(canvas, copy->scale_mode); + set_clip(canvas, clip); + gdi_draw_bitmap_redrop(canvas->dc, ©->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, ©->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, ©->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, ©->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, ©->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 -- cgit