From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/bitblt.c | 115 +++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 44 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index dda5262c6f8..7390f294d19 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1570,20 +1570,25 @@ DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo return ret; }
+struct x11drv_image +{ + XImage *ximage; /* XImage used for X11 drawing */ + void *data; /* pixels allocated for XImage */ +#ifdef HAVE_LIBXXSHM + XShmSegmentInfo shminfo; +#endif +};
struct x11drv_window_surface { struct window_surface header; Window window; GC gc; - XImage *image; + struct x11drv_image *image; BOOL byteswap; BOOL is_argb; DWORD alpha_bits; COLORREF color_key; -#ifdef HAVE_LIBXXSHM - XShmSegmentInfo shminfo; -#endif BITMAPINFO info; /* variable size, must be last */ };
@@ -1824,6 +1829,45 @@ failed: } #endif /* HAVE_LIBXXSHM */
+static void x11drv_image_destroy( struct x11drv_image *image ) +{ +#ifdef HAVE_LIBXXSHM + if (image->shminfo.shmid != -1) + { + XShmDetach( gdi_display, &image->shminfo ); + shmdt( image->shminfo.shmaddr ); + } +#endif + + image->ximage->data = NULL; /* avoid XDestroyImage freeing the data */ + XDestroyImage( image->ximage ); + image->ximage = NULL; + + free( image->data ); +} + +static struct x11drv_image *x11drv_image_create( const BITMAPINFO *info, const XVisualInfo *vis ) +{ + struct x11drv_image *image; + + if (!(image = calloc( 1, sizeof(*image) ))) return NULL; +#ifdef HAVE_LIBXXSHM + image->ximage = create_shm_image( vis, info->bmiHeader.biWidth, abs( info->bmiHeader.biHeight ), &image->shminfo ); +#endif + if (!image->ximage) image->ximage = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL, + info->bmiHeader.biWidth, abs( info->bmiHeader.biHeight ), 32, 0 ); + if (!image->ximage) goto failed; + + if (!image->ximage->data) image->ximage->data = image->data = malloc( info->bmiHeader.biSizeImage ); + if (!image->ximage->data) goto failed; + return image; + +failed: + if (image) XDestroyImage( image->ximage ); + free( image ); + return NULL; +} + /*********************************************************************** * x11drv_surface_get_bitmap_info */ @@ -1878,15 +1922,16 @@ static void x11drv_surface_set_clip( struct window_surface *window_surface, cons static BOOL x11drv_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty ) { struct x11drv_window_surface *surface = get_x11_surface( window_surface ); + XImage *ximage = surface->image->ximage; unsigned char *src = window_surface->color_bits; - unsigned char *dst = (unsigned char *)surface->image->data; + unsigned char *dst = (unsigned char *)ximage->data;
if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface, window_surface->color_bits );
if (src != dst) { - int map[256], *mapping = get_window_surface_mapping( surface->image->bits_per_pixel, map ); - int width_bytes = surface->image->bytes_per_line; + int map[256], *mapping = get_window_surface_mapping( ximage->bits_per_pixel, map ); + int width_bytes = ximage->bytes_per_line;
src += dirty->top * width_bytes; dst += dirty->top * width_bytes; @@ -1895,7 +1940,7 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R } else if (surface->alpha_bits) { - int x, y, stride = surface->image->bytes_per_line / sizeof(ULONG); + int x, y, stride = ximage->bytes_per_line / sizeof(ULONG); ULONG *ptr = (ULONG *)dst + dirty->top * stride;
for (y = dirty->top; y < dirty->bottom; y++, ptr += stride) @@ -1904,13 +1949,13 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R }
#ifdef HAVE_LIBXXSHM - if (surface->shminfo.shmid != -1) - XShmPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, + if (surface->image->shminfo.shmid != -1) + XShmPutImage( gdi_display, surface->window, surface->gc, ximage, dirty->left, dirty->top, rect->left + dirty->left, rect->top + dirty->top, dirty->right - dirty->left, dirty->bottom - dirty->top, False ); else #endif - XPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, + XPutImage( gdi_display, surface->window, surface->gc, ximage, dirty->left, dirty->top, rect->left + dirty->left, rect->top + dirty->top, dirty->right - dirty->left, dirty->bottom - dirty->top ); XFlush( gdi_display ); @@ -1927,22 +1972,7 @@ static void x11drv_surface_destroy( struct window_surface *window_surface )
TRACE( "freeing %p bits %p\n", surface, window_surface->color_bits ); if (surface->gc) XFreeGC( gdi_display, surface->gc ); - if (surface->image) - { - if (surface->image->data != window_surface->color_bits) free( window_surface->color_bits ); -#ifdef HAVE_LIBXXSHM - if (surface->shminfo.shmid != -1) - { - XShmDetach( gdi_display, &surface->shminfo ); - shmdt( surface->shminfo.shmaddr ); - } - else -#endif - free( surface->image->data ); - surface->image->data = NULL; - XDestroyImage( surface->image ); - } - + if (surface->image) x11drv_image_destroy( surface->image ); free( surface ); }
@@ -1966,6 +1996,8 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn struct x11drv_window_surface *surface; int width = rect->right - rect->left, height = rect->bottom - rect->top; int colors = format->bits_per_pixel <= 8 ? 1 << format->bits_per_pixel : 3; + struct x11drv_image *image; + UINT size;
info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biWidth = width; @@ -1975,8 +2007,15 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn info->bmiHeader.biSizeImage = get_dib_image_size( info ); if (format->bits_per_pixel > 8) set_color_info( vis, info, use_alpha );
- surface = calloc( 1, FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] )); - if (!surface) return NULL; + size = FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] ); + if (!(image = x11drv_image_create( info, vis ))) return NULL; + if (!(surface = calloc( 1, size ))) + { + x11drv_image_destroy( image ); + return NULL; + } + surface->image = image; + if (!window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, info, 0 )) goto failed; memcpy( &surface->info, info, get_dib_info_size( info, DIB_RGB_COLORS ) );
@@ -1984,21 +2023,9 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn surface->is_argb = (use_alpha && vis->depth == 32 && info->bmiHeader.biCompression == BI_RGB); set_color_key( surface, color_key );
-#ifdef HAVE_LIBXXSHM - surface->image = create_shm_image( vis, width, height, &surface->shminfo ); - if (!surface->image) -#endif - { - surface->image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL, - width, height, 32, 0 ); - if (!surface->image) goto failed; - surface->image->data = malloc( info->bmiHeader.biSizeImage ); - if (!surface->image->data) goto failed; - } - surface->gc = XCreateGC( gdi_display, window, 0, NULL ); XSetSubwindowMode( gdi_display, surface->gc, IncludeInferiors ); - surface->byteswap = image_needs_byteswap( surface->image, is_r8g8b8(vis), format->bits_per_pixel ); + surface->byteswap = image_needs_byteswap( surface->image->ximage, is_r8g8b8(vis), format->bits_per_pixel );
if (vis->depth == 32 && !surface->is_argb) surface->alpha_bits = ~(vis->red_mask | vis->green_mask | vis->blue_mask); @@ -2009,11 +2036,11 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn if (!(surface->header.color_bits = calloc( 1, info->bmiHeader.biSizeImage ))) goto failed; } - else surface->header.color_bits = surface->image->data; + else surface->header.color_bits = surface->image->ximage->data;
TRACE( "created %p for %lx %s color_bits %p-%p image %p\n", surface, window, wine_dbgstr_rect(rect), surface->header.color_bits, (char *)surface->header.color_bits + info->bmiHeader.biSizeImage, - surface->image->data ); + surface->image->ximage->data );
return &surface->header;