diff options
-rw-r--r-- | gdi_canvas.c | 157 | ||||
-rw-r--r-- | gdi_canvas.h | 2 |
2 files changed, 112 insertions, 47 deletions
diff --git a/gdi_canvas.c b/gdi_canvas.c index 4362b38..db1975a 100644 --- a/gdi_canvas.c +++ b/gdi_canvas.c @@ -31,7 +31,7 @@ typedef struct GdiCanvas GdiCanvas; struct GdiCanvas { CanvasBase base; HDC dc; - Mutex* lock; + RecurciveMutex* lock; }; @@ -635,10 +635,12 @@ static inline COLORREF get_color_ref(GdiCanvas *canvas, uint32_t color) return RGB(r, g, b); } -static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush) +static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush, RecurciveMutex **brush_lock) { HBRUSH hbrush; + *brush_lock = NULL; + switch (brush->type) { case SPICE_BRUSH_TYPE_SOLID: if (!(hbrush = CreateSolidBrush(get_color_ref(canvas, brush->u.color)))) { @@ -660,6 +662,7 @@ static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush) if (!bitmap) { CANVAS_ERROR("GetCurrentObject failed"); } + *brush_lock = gdi_surface->lock; } else { surface = canvas_get_image(&canvas->base, brush->u.pattern.pat); surface_to_image(surface, &image); @@ -911,6 +914,7 @@ static void draw_str_mask_bitmap(struct GdiCanvas *canvas, uint8_t *bitmap_data; HBRUSH prev_hbrush; HBRUSH hbrush; + RecurciveMutex *brush_lock; bitmap.hbitmap = (HBITMAP)1; if (!(surface = canvas_get_str_mask(&canvas->base, str, n, &pos))) { @@ -960,9 +964,14 @@ static void draw_str_mask_bitmap(struct GdiCanvas *canvas, dest_stride = dest_stride + 3; dest_stride = dest_stride & ~3; - hbrush = get_brush(canvas, brush); + hbrush = get_brush(canvas, brush, &brush_lock); prev_hbrush = set_brush(bitmap.dc, hbrush, brush); - gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); + } else { + gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); + } unset_brush(bitmap.dc, prev_hbrush); @@ -974,7 +983,7 @@ static void draw_str_mask_bitmap(struct GdiCanvas *canvas, BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); AlphaBlend(canvas->dc, dest->left, dest->top, dest->right - dest->left, dest->bottom - dest->top, bitmap.dc, src->left, src->top, src->right - src->left, src->bottom - src->top, bf); @@ -1022,10 +1031,11 @@ static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi HBRUSH prev_hbrush; HBRUSH brush; struct BitmapData bitmapmask; + RecurciveMutex *brush_lock; - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); - if (!(brush = get_brush(canvas, &fill->brush))) { + if (!(brush = get_brush(canvas, &fill->brush, &brush_lock))) { CANVAS_ERROR("no braash"); return; } @@ -1034,8 +1044,14 @@ static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi set_clip(canvas, clip); prev_hbrush = set_brush(canvas->dc, brush, &fill->brush); - gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, - fill->rop_decriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, + fill->rop_decriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); + } else { + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, + fill->rop_decriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); + } free_mask(&bitmapmask); unset_brush(canvas->dc, prev_hbrush); @@ -1052,7 +1068,8 @@ static void gdi_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, copy->src_bitmap); if (gdi_surface) { - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); bitmapmask = get_mask_bitmap(canvas, ©->mask); set_scale_mode(canvas, copy->scale_mode); set_clip(canvas, clip); @@ -1062,7 +1079,7 @@ static void gdi_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi surface = canvas_get_image(&canvas->base, copy->src_bitmap); pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); bitmapmask = get_mask_bitmap(canvas, ©->mask); set_scale_mode(canvas, copy->scale_mode); set_clip(canvas, clip); @@ -1104,7 +1121,7 @@ static void gdi_canvas_put_image(SpiceCanvas *spice_canvas, HDC dc, const SpiceR int num_rects; pixman_box32_t *rects; - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); set_scale_mode(canvas, SPICE_IMAGE_SCALE_MODE_NEAREST); if (clip) { rects = pixman_region32_rectangles((pixman_region32_t*)clip, &num_rects); @@ -1194,14 +1211,15 @@ static void gdi_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bb gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, transparent->src_bitmap); if (gdi_surface) { - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); set_clip(canvas, clip); gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, gdi_surface->dc, transparent->true_color); } else { surface = canvas_get_image(&canvas->base, transparent->src_bitmap); pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); set_clip(canvas, clip); if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { HDC dc; @@ -1276,7 +1294,8 @@ static void gdi_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bb gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, alpha_blend->src_bitmap); if (gdi_surface) { - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); set_clip(canvas, clip); use_bitmap_alpha = 0; gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, gdi_surface->dc, @@ -1286,7 +1305,7 @@ static void gdi_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bb use_bitmap_alpha = pixman_image_get_depth(surface) == 32; pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); set_clip(canvas, clip); if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { HDC dc; @@ -1321,26 +1340,33 @@ static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, S HBRUSH prev_hbrush; HBRUSH hbrush; uint8_t rop3; + RecurciveMutex *brush_lock; rop3 = calc_rop3_src_brush(opaque->rop_decriptor); gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, opaque->src_bitmap); if (gdi_surface) { - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); bitmapmask = get_mask_bitmap(canvas, &opaque->mask); - hbrush = get_brush(canvas, &opaque->brush); + hbrush = get_brush(canvas, &opaque->brush, &brush_lock); 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); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3); + } else { + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3); + } unset_brush(canvas->dc, prev_hbrush); } else { surface = canvas_get_image(&canvas->base, opaque->src_bitmap); pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); bitmapmask = get_mask_bitmap(canvas, &opaque->mask); - hbrush = get_brush(canvas, &opaque->brush); + hbrush = get_brush(canvas, &opaque->brush, &brush_lock); set_scale_mode(canvas, opaque->scale_mode); set_clip(canvas, clip); prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush); @@ -1351,14 +1377,25 @@ static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, S dc = create_compatible_dc(); prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3); + } else { + 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); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, image.pixels, + image.stride, image.width, image.height, &bitmapmask, rop3, 0); + } else { + 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); @@ -1378,7 +1415,8 @@ static void gdi_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, Sp gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, blend->src_bitmap); if (gdi_surface) { - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); bitmapmask = get_mask_bitmap(canvas, &blend->mask); set_scale_mode(canvas, blend->scale_mode); set_clip(canvas, clip); @@ -1388,7 +1426,7 @@ static void gdi_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, Sp surface = canvas_get_image(&canvas->base, blend->src_bitmap); pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); bitmapmask = get_mask_bitmap(canvas, &blend->mask); set_scale_mode(canvas, blend->scale_mode); set_clip(canvas, clip); @@ -1421,7 +1459,7 @@ static void gdi_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox GdiCanvas *canvas = (GdiCanvas *)spice_canvas; struct BitmapData bitmapmask; - Lock lock(*canvas->lock); + RecurciveLock 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); @@ -1434,7 +1472,7 @@ static void gdi_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, S GdiCanvas *canvas = (GdiCanvas *)spice_canvas; struct BitmapData bitmapmask; - Lock lock(*canvas->lock); + RecurciveLock 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); @@ -1447,7 +1485,7 @@ static void gdi_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox GdiCanvas *canvas = (GdiCanvas *)spice_canvas; struct BitmapData bitmapmask; - Lock lock(*canvas->lock); + RecurciveLock 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); @@ -1465,23 +1503,31 @@ static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi HBRUSH prev_hbrush; HBRUSH hbrush; PixmanData *pixman_data; + RecurciveMutex *brush_lock; gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, rop3->src_bitmap); if (gdi_surface) { - Lock lock(*canvas->lock); - hbrush = get_brush(canvas, &rop3->brush); + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + hbrush = get_brush(canvas, &rop3->brush, &brush_lock); 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); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc, + &bitmapmask, rop3->rop3); + } else { + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc, + &bitmapmask, rop3->rop3); + } unset_brush(canvas->dc, prev_hbrush); } else { 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); + RecurciveLock lock(*canvas->lock); + hbrush = get_brush(canvas, &rop3->brush, &brush_lock); bitmapmask = get_mask_bitmap(canvas, &rop3->mask); set_scale_mode(canvas, rop3->scale_mode); set_clip(canvas, clip); @@ -1493,15 +1539,27 @@ static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi 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); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc, + &bitmapmask, rop3->rop3); + } else { + 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, + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, image.pixels, image.stride, image.width, image.height, &bitmapmask, rop3->rop3, 0); + } else { + 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); @@ -1514,7 +1572,7 @@ static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi static void gdi_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos) { GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); set_clip(canvas, clip); @@ -1526,8 +1584,9 @@ static void gdi_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi { GdiCanvas *canvas = (GdiCanvas *)spice_canvas; SpiceString *str; + RecurciveMutex *brush_lock; - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); set_clip(canvas, clip); lock.unlock(); @@ -1535,11 +1594,17 @@ static void gdi_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi HBRUSH prev_hbrush; HBRUSH hbrush; - Lock lock(*canvas->lock); - hbrush = get_brush(canvas, &text->back_brush); + RecurciveLock lock(*canvas->lock); + hbrush = get_brush(canvas, &text->back_brush, &brush_lock); 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); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL, + text->back_mode, 1); + } else { + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL, + text->back_mode, 1); + } unset_brush(canvas->dc, prev_hbrush); } @@ -1644,7 +1709,7 @@ static void gdi_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, S surface = canvas_get_image(&canvas->base, stroke->brush.u.pattern.pat); } - Lock lock(*canvas->lock); + RecurciveLock lock(*canvas->lock); set_clip(canvas, clip); switch (stroke->fore_mode) { @@ -1819,7 +1884,7 @@ static int need_init = 1; static SpiceCanvasOps gdi_canvas_ops; SpiceCanvas *gdi_canvas_create(int width, int height, - HDC dc, Mutex* lock, int bits + HDC dc, RecurciveMutex* lock, int bits #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache diff --git a/gdi_canvas.h b/gdi_canvas.h index 73d6978..e0a43d5 100644 --- a/gdi_canvas.h +++ b/gdi_canvas.h @@ -34,7 +34,7 @@ typedef struct { } GdiImage; SpiceCanvas *gdi_canvas_create(int width, int height, - HDC dc, class Mutex *lock, int bits, + HDC dc, class RecurciveMutex *lock, int bits, SpiceImageCache *bits_cache, SpicePaletteCache *palette_cache, SpiceImageSurfaces *surfaces, |