From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 82 +++++++++++++++++++- dlls/winex11.drv/bitblt.c | 159 -------------------------------------- 2 files changed, 79 insertions(+), 162 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 43b81e4e738..1f8d1e4c3e2 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -174,7 +174,6 @@ static COLORREF get_color_key( const BITMAPINFO *info, COLORREF color_key ) if (color_key & (1 << 24)) /* PALETTEINDEX */ return 0; if (color_key >> 16 == 0x10ff) /* DIBINDEX */ return 0;
- if (info->bmiHeader.biBitCount == 24) return color_key; if (info->bmiHeader.biCompression == BI_BITFIELDS) { UINT *masks = (UINT *)info->bmiColors; @@ -222,12 +221,34 @@ static void *window_surface_get_shape( struct window_surface *surface, BITMAPINF return gdi_bits.ptr; }
+static BYTE shape_from_alpha_mask( UINT32 *bits, UINT32 alpha_mask, UINT32 alpha ) +{ + BYTE i, bit, mask = 0; + for (i = 0, bit = 7; i < 8; i++, bit--) mask |= ((bits[i] & alpha_mask) == alpha) << bit; + return ~mask; +} + +static BYTE shape_from_color_key_16( UINT16 *bits, UINT16 color_mask, UINT16 color_key ) +{ + BYTE i, bit, mask = 0; + for (i = 0, bit = 7; i < 8; i++, bit--) mask |= ((bits[i] & color_mask) == color_key) << bit; + return ~mask; +} + +static BYTE shape_from_color_key_32( UINT32 *bits, UINT32 color_mask, UINT32 color_key ) +{ + BYTE i, bit, mask = 0; + for (i = 0, bit = 7; i < 8; i++, bit--) mask |= ((bits[i] & color_mask) == color_key) << bit; + return ~mask; +} + static void set_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, void *color_bits ) { - UINT width, height, shape_stride; + UINT width, height, x, y, shape_stride, color_stride, alpha_mask = surface->alpha_mask; char shape_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *shape_info = (BITMAPINFO *)shape_buf; + COLORREF color_key = surface->color_key; RECT *shape_rect, tmp_rect; WINEREGION *data; void *shape_bits; @@ -239,7 +260,9 @@ static void set_surface_shape( struct window_surface *surface, const RECT *rect, if (!surface->shape_bitmap) surface->shape_bitmap = NtGdiCreateBitmap( width, height, 1, 1, NULL ); if (!(shape_bits = window_surface_get_shape( surface, shape_info ))) return;
+ color_stride = color_info->bmiHeader.biSizeImage / height; shape_stride = shape_info->bmiHeader.biSizeImage / abs( shape_info->bmiHeader.biHeight ); + if (!surface->shape_region) set_surface_shape_rect( shape_bits, shape_stride, dirty ); else if ((data = GDI_GetObjPtr( surface->shape_region, NTGDI_OBJ_REGION ))) { @@ -252,6 +275,59 @@ static void set_surface_shape( struct window_surface *surface, const RECT *rect, GDI_ReleaseObj( surface->shape_region ); }
+ switch (color_info->bmiHeader.biBitCount) + { + case 16: + { + UINT *masks = (UINT *)color_info->bmiColors, color_mask; + BYTE *shape = shape_bits, *color = color_bits; + + if (color_key == CLR_INVALID) color_mask = 0; + else color_mask = masks[0] | masks[1] | masks[2]; + if (!color_mask) break; + + color += dirty->top * color_stride; + shape += dirty->top * shape_stride; + + for (y = dirty->top; y < dirty->bottom; y++, color += color_stride, shape += shape_stride) + { + for (x = dirty->left; x < dirty->right; x += 8) + { + shape[x / 8] &= shape_from_color_key_16( (UINT16 *)color + x, color_mask, color_key ); + } + } + break; + } + case 24: case 32: + { + BYTE *shape = shape_bits, *color = color_bits; + UINT color_mask, alpha = 0; + + if (color_key == CLR_INVALID) color_mask = 0; + else if (color_info->bmiHeader.biCompression == BI_RGB) color_mask = 0xffffff; + else + { + UINT *masks = (UINT *)color_info->bmiColors; + color_mask = masks[0] | masks[1] | masks[2]; + } + if (!alpha_mask && !color_mask) break; + if (!alpha_mask) alpha = -1; + + color += dirty->top * color_stride; + shape += dirty->top * shape_stride; + + for (y = dirty->top; y < dirty->bottom; y++, color += color_stride, shape += shape_stride) + { + for (x = dirty->left; x < dirty->right; x += 8) + { + shape[x / 8] &= shape_from_alpha_mask( (UINT32 *)color + x, alpha_mask, alpha ); + shape[x / 8] &= shape_from_color_key_32( (UINT32 *)color + x, color_mask, color_key ); + } + } + break; + } + } + surface->funcs->set_shape( surface, shape_info, shape_bits ); }
@@ -270,7 +346,7 @@ static void update_surface_shape( struct window_surface *surface, const RECT *re { if (surface == &dummy_surface) return;
- if (surface->shape_region) + if (surface->shape_region || surface->alpha_mask || surface->color_key != CLR_INVALID) set_surface_shape( surface, rect, dirty, color_info, color_bits ); else clear_surface_shape( surface ); diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index a7d41e37d79..0d27f6b847f 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1596,162 +1596,6 @@ static struct x11drv_window_surface *get_x11_surface( struct window_surface *sur return (struct x11drv_window_surface *)surface; }
-#ifdef HAVE_LIBXSHAPE -static inline void flush_rgn_data( HRGN rgn, RGNDATA *data ) -{ - HRGN tmp = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - NtGdiCombineRgn( rgn, rgn, tmp, RGN_OR ); - NtGdiDeleteObjectApp( tmp ); - data->rdh.nCount = 0; -} - -static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len ) -{ - RECT *rect = (RECT *)data->Buffer + data->rdh.nCount; - - if (len <= 0) return; - rect->left = x; - rect->top = y; - rect->right = x + len; - rect->bottom = y + 1; - data->rdh.nCount++; - if (data->rdh.nCount * sizeof(RECT) > data->rdh.nRgnSize - sizeof(RECT)) - flush_rgn_data( rgn, data ); -} -#endif - -/*********************************************************************** - * update_surface_region - */ -static void update_surface_region( struct x11drv_window_surface *surface, const BITMAPINFO *info, const void *color_bits, - COLORREF color_key, UINT alpha_mask ) -{ -#ifdef HAVE_LIBXSHAPE - char buffer[4096]; - RGNDATA *data = (RGNDATA *)buffer; - UINT *masks = (UINT *)info->bmiColors; - int x, y, start, width; - HRGN rgn; - - if (!shape_layered_windows) return; - - if (!alpha_mask && color_key == CLR_INVALID) - { - XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); - return; - } - - data->rdh.dwSize = sizeof(data->rdh); - data->rdh.iType = RDH_RECTANGLES; - data->rdh.nCount = 0; - data->rdh.nRgnSize = sizeof(buffer) - sizeof(data->rdh); - - rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - width = surface->header.rect.right - surface->header.rect.left; - - switch (info->bmiHeader.biBitCount) - { - case 16: - { - const WORD *bits = color_bits; - int stride = (width + 1) & ~1; - UINT mask = masks[0] | masks[1] | masks[2]; - - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride) - { - x = 0; - while (x < width) - { - while (x < width && (bits[x] & mask) == color_key) x++; - start = x; - while (x < width && (bits[x] & mask) != color_key) x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - break; - } - case 24: - { - const BYTE *bits = color_bits; - int stride = (width * 3 + 3) & ~3; - - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride) - { - x = 0; - while (x < width) - { - while (x < width && - (bits[x * 3] == GetBValue(color_key)) && - (bits[x * 3 + 1] == GetGValue(color_key)) && - (bits[x * 3 + 2] == GetRValue(color_key))) - x++; - start = x; - while (x < width && - ((bits[x * 3] != GetBValue(color_key)) || - (bits[x * 3 + 1] != GetGValue(color_key)) || - (bits[x * 3 + 2] != GetRValue(color_key)))) - x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - break; - } - case 32: - { - const DWORD *bits = color_bits; - - if (info->bmiHeader.biCompression == BI_RGB) - { - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width) - { - x = 0; - while (x < width) - { - while (x < width && - ((bits[x] & 0xffffff) == color_key || - (alpha_mask && !(bits[x] & alpha_mask)))) x++; - start = x; - while (x < width && - !((bits[x] & 0xffffff) == color_key || - (alpha_mask && !(bits[x] & alpha_mask)))) x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - } - else - { - UINT mask = masks[0] | masks[1] | masks[2]; - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width) - { - x = 0; - while (x < width) - { - while (x < width && (bits[x] & mask) == color_key) x++; - start = x; - while (x < width && (bits[x] & mask) != color_key) x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - } - break; - } - default: - assert(0); - } - - if (data->rdh.nCount) flush_rgn_data( rgn, data ); - - if ((data = X11DRV_GetRegionData( rgn, 0 ))) - { - XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0, - (XRectangle *)data->Buffer, data->rdh.nCount, ShapeSet, YXBanded ); - free( data ); - } - - NtGdiDeleteObjectApp( rgn ); -#endif -} - #ifdef HAVE_LIBXXSHM static int xshm_error_handler( Display *display, XErrorEvent *event, void *arg ) { @@ -1975,13 +1819,10 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R { UINT alpha_mask = window_surface->alpha_mask, alpha_bits = window_surface->alpha_bits; struct x11drv_window_surface *surface = get_x11_surface( window_surface ); - COLORREF color_key = window_surface->color_key; XImage *ximage = surface->image->ximage; const unsigned char *src = color_bits; unsigned char *dst = (unsigned char *)ximage->data;
- if (alpha_mask || color_key != CLR_INVALID) update_surface_region( surface, color_info, color_bits, color_key, alpha_mask ); - if (alpha_bits == -1) { if (alpha_mask || color_info->bmiHeader.biBitCount != 32) alpha_bits = 0;