diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 853f2aef942..413f4e48595 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1461,3 +1461,62 @@ DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, wine_tsx11_unlock(); return ret; } + + +/*********************************************************************** + * get_pixmap_image + * + * Equivalent of X11DRV_GetImage that reads directly from a pixmap. + */ +DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis, + BITMAPINFO *info, struct gdi_image_bits *bits ) +{ + DWORD ret = ERROR_SUCCESS; + XImage *image; + struct gdi_image_bits src_bits; + struct bitblt_coords coords; + const XPixmapFormatValues *format = pixmap_formats[vis->depth]; + const int *mapping = NULL; + + if (!format) return ERROR_INVALID_PARAMETER; + + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = -height; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = format->bits_per_pixel; + info->bmiHeader.biXPelsPerMeter = 0; + info->bmiHeader.biYPelsPerMeter = 0; + info->bmiHeader.biClrImportant = 0; + set_color_info( vis, info ); + + if (!bits) return ERROR_SUCCESS; /* just querying the color information */ + + coords.x = 0; + coords.y = 0; + coords.width = width; + coords.height = height; + SetRect( &coords.visrect, 0, 0, width, height ); + + wine_tsx11_lock(); + image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap ); + wine_tsx11_unlock(); + if (!image) return ERROR_OUTOFMEMORY; + + info->bmiHeader.biSizeImage = height * image->bytes_per_line; + + src_bits.ptr = image->data; + src_bits.is_copy = TRUE; + ret = copy_image_bits( info, is_r8g8b8(vis), image, &src_bits, bits, &coords, mapping, + zeropad_masks[(width * image->bits_per_pixel) & 31] ); + + if (!ret && bits->ptr == image->data) + { + bits->free = free_ximage_bits; + image->data = NULL; + } + wine_tsx11_lock(); + XDestroyImage( image ); + wine_tsx11_unlock(); + return ret; +} diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 95c11696e6f..68854f068ef 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -2199,68 +2199,14 @@ static void flush_pixmap( struct wine_glcontext *ctx ) { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; - XImage *image; - struct gdi_image_bits src_bits, bits; - struct bitblt_coords coords; - DWORD *masks; - BOOL is_r8g8b8 = FALSE; - const XPixmapFormatValues *format = pixmap_formats[ctx->vis->depth]; + struct gdi_image_bits bits; - coords.x = 0; - coords.y = 0; - coords.width = ctx->pixmap_size.cx; - coords.height = ctx->pixmap_size.cy; - SetRect( &coords.visrect, 0, 0, coords.width, coords.height ); - - info->bmiHeader.biSize = sizeof(info->bmiHeader); - info->bmiHeader.biWidth = coords.width; - info->bmiHeader.biHeight = -coords.height; - info->bmiHeader.biPlanes = 1; - info->bmiHeader.biBitCount = format->bits_per_pixel; - info->bmiHeader.biCompression = BI_RGB; - info->bmiHeader.biClrUsed = 0; - switch (info->bmiHeader.biBitCount) - { - case 16: - masks = (DWORD *)info->bmiColors; - masks[0] = ctx->vis->red_mask; - masks[1] = ctx->vis->green_mask; - masks[2] = ctx->vis->blue_mask; - info->bmiHeader.biCompression = BI_BITFIELDS; - break; - case 24: - is_r8g8b8 = (ctx->vis->red_mask == 0xff0000 && ctx->vis->blue_mask == 0x0000ff); - break; - case 32: - masks = (DWORD *)info->bmiColors; - masks[0] = ctx->vis->red_mask; - masks[1] = ctx->vis->green_mask; - masks[2] = ctx->vis->blue_mask; - if (masks[0] != 0xff0000 || masks[1] != 0x00ff00 || masks[2] != 0x0000ff) - info->bmiHeader.biCompression = BI_BITFIELDS; - break; - default: - FIXME( "depth %u not supported\n", info->bmiHeader.biBitCount ); - return; - } - - wine_tsx11_lock(); - image = XGetImage( gdi_display, ctx->pixmap, 0, 0, coords.width, coords.height, AllPlanes, ZPixmap ); - wine_tsx11_unlock(); - if (!image) return; - - src_bits.ptr = image->data; - src_bits.is_copy = TRUE; - if (!copy_image_bits( info, is_r8g8b8, image, &src_bits, &bits, &coords, NULL, ~0u )) + if (!get_pixmap_image( ctx->pixmap, ctx->pixmap_size.cx, ctx->pixmap_size.cy, ctx->vis, info, &bits )) { HBITMAP bitmap = GetCurrentObject( ctx->hdc, OBJ_BITMAP ); - TRACE( "drawable %lx -> hdc %p bitmap %p\n", ctx->pixmap, ctx->hdc, bitmap ); - SetDIBits( 0, bitmap, 0, coords.height, bits.ptr, info, DIB_RGB_COLORS ); + SetDIBits( 0, bitmap, 0, ctx->pixmap_size.cy, bits.ptr, info, DIB_RGB_COLORS ); if (bits.free) bits.free( &bits ); } - wine_tsx11_lock(); - XDestroyImage( image ); - wine_tsx11_unlock(); } static void flush_gl_drawable( struct glx_physdev *physdev ) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 82889c2412c..d17565bcfc9 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -229,6 +229,8 @@ extern Pixmap X11DRV_get_pixmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN; extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits, struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask ) DECLSPEC_HIDDEN; +extern DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis, + BITMAPINFO *info, struct gdi_image_bits *bits ) DECLSPEC_HIDDEN; extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN; extern BOOL add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN;