This should help unifying the interface and get rid of the get_info callback.
Later, I think we could create bitmaps over sections shared with some DWM process and/or host compositor.
-- v3: win32u: Create a HBITMAP backing the window surface pixels. winex11: Create a HBITMAP for the allocated surface pixels. winex11: Create XImage before initializing the window surface. winex11: Simplify the XSHM extension function calls. win32u: Pass BITMAPINFO and a HBITMAP to window_surface_init. win32u: Move the window surface color bits to the common struct.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 5 ++--- dlls/wineandroid.drv/window.c | 15 +++++++------- dlls/winemac.drv/surface.c | 21 +++++++++---------- dlls/winewayland.drv/window_surface.c | 28 ++++++++++++-------------- dlls/winex11.drv/bitblt.c | 29 +++++++++++++-------------- include/wine/gdi_driver.h | 5 +++-- 6 files changed, 49 insertions(+), 54 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 02b11db4dd5..6bb090cedcf 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -113,7 +113,6 @@ struct window_surface dummy_surface = struct offscreen_window_surface { struct window_surface header; - char *bits; BITMAPINFO info; };
@@ -129,7 +128,7 @@ static void *offscreen_window_surface_get_bitmap_info( struct window_surface *ba { struct offscreen_window_surface *impl = impl_from_window_surface( base ); info->bmiHeader = impl->info.bmiHeader; - return impl->bits; + return base->color_bits; }
static void offscreen_window_surface_set_clip( struct window_surface *base, const RECT *rects, UINT count ) @@ -182,7 +181,7 @@ void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struc if (!(impl = calloc(1, offsetof( struct offscreen_window_surface, info.bmiColors[0] ) + size))) return; window_surface_init( &impl->header, &offscreen_window_surface_funcs, hwnd, &surface_rect );
- impl->bits = (char *)&impl->info.bmiColors[0]; + impl->header.color_bits = (char *)&impl->info.bmiColors[0]; impl->info.bmiHeader.biSize = sizeof( impl->info ); impl->info.bmiHeader.biWidth = surface_rect.right; impl->info.bmiHeader.biHeight = surface_rect.bottom; diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index de1de330181..657a5ff62cc 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -575,7 +575,6 @@ struct android_window_surface RECT *clip_rects; BYTE alpha; COLORREF color_key; - void *bits; BITMAPINFO info; /* variable size, must be last */ };
@@ -643,7 +642,7 @@ static void *android_surface_get_bitmap_info( struct window_surface *window_surf struct android_window_surface *surface = get_android_surface( window_surface );
memcpy( info, &surface->info, get_dib_info_size( &surface->info, DIB_RGB_COLORS )); - return surface->bits; + return window_surface->color_bits; }
/*********************************************************************** @@ -688,7 +687,7 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const locked.bottom = rc.bottom; intersect_rect( &locked, &locked, rect );
- src = (DWORD *)surface->bits + (locked.top - rect->top) * surface->info.bmiHeader.biWidth + + src = (DWORD *)window_surface->color_bits + (locked.top - rect->top) * surface->info.bmiHeader.biWidth + (locked.left - rect->left); dst = (DWORD *)buffer.bits + locked.top * buffer.stride + locked.left; width = min( locked.right - locked.left, buffer.stride ); @@ -733,11 +732,11 @@ static void android_surface_destroy( struct window_surface *window_surface ) { struct android_window_surface *surface = get_android_surface( window_surface );
- TRACE( "freeing %p bits %p\n", surface, surface->bits ); + TRACE( "freeing %p bits %p\n", surface, window_surface->color_bits );
free( surface->clip_rects ); release_ioctl_window( surface->window ); - free( surface->bits ); + free( window_surface->color_bits ); free( surface ); }
@@ -797,11 +796,11 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, surface->alpha = alpha; set_color_key( surface, color_key );
- if (!(surface->bits = malloc( surface->info.bmiHeader.biSizeImage ))) + if (!(surface->header.color_bits = malloc( surface->info.bmiHeader.biSizeImage ))) goto failed;
- TRACE( "created %p hwnd %p %s bits %p-%p\n", surface, hwnd, wine_dbgstr_rect(rect), - surface->bits, (char *)surface->bits + surface->info.bmiHeader.biSizeImage ); + TRACE( "created %p hwnd %p %s color_bits %p-%p\n", surface, hwnd, wine_dbgstr_rect(rect), + surface->header.color_bits, (char *)surface->header.color_bits + surface->info.bmiHeader.biSizeImage );
return &surface->header;
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 285561e6d02..a34df22397a 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -65,7 +65,6 @@ struct macdrv_window_surface struct window_surface header; macdrv_window window; BOOL use_alpha; - BYTE *bits; BITMAPINFO info; /* variable size, must be last */ };
@@ -80,7 +79,7 @@ static void *macdrv_surface_get_bitmap_info(struct window_surface *window_surfac struct macdrv_window_surface *surface = get_mac_surface(window_surface);
memcpy(info, &surface->info, get_dib_info_size(&surface->info, DIB_RGB_COLORS)); - return surface->bits; + return window_surface->color_bits; }
/*********************************************************************** @@ -107,8 +106,8 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) { struct macdrv_window_surface *surface = get_mac_surface(window_surface);
- TRACE("freeing %p bits %p\n", surface, surface->bits); - free(surface->bits); + TRACE("freeing %p bits %p\n", surface, window_surface->color_bits); + free(window_surface->color_bits); free(surface); }
@@ -158,13 +157,13 @@ struct window_surface *create_surface(HWND hwnd, macdrv_window window, const REC surface->window = window; if (old_surface) surface->header.bounds = old_surface->bounds; surface->use_alpha = use_alpha; - surface->bits = malloc(surface->info.bmiHeader.biSizeImage); - if (!surface->bits) goto failed; + surface->header.color_bits = malloc(surface->info.bmiHeader.biSizeImage); + if (!surface->header.color_bits) goto failed; window_background = macdrv_window_background_color(); - memset_pattern4(surface->bits, &window_background, surface->info.bmiHeader.biSizeImage); + memset_pattern4(surface->header.color_bits, &window_background, surface->info.bmiHeader.biSizeImage);
- TRACE("created %p for %p %s bits %p-%p\n", surface, window, wine_dbgstr_rect(rect), - surface->bits, surface->bits + surface->info.bmiHeader.biSizeImage); + TRACE("created %p for %p %s color_bits %p-%p\n", surface, window, wine_dbgstr_rect(rect), + surface->header.color_bits, (char *)surface->header.color_bits + surface->info.bmiHeader.biSizeImage);
return &surface->header;
@@ -229,12 +228,12 @@ CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surfac
if (copy_data) { - CFDataRef data = CFDataCreate(NULL, (UInt8*)surface->bits + offset, size); + CFDataRef data = CFDataCreate(NULL, (UInt8 *)window_surface->color_bits + offset, size); provider = CGDataProviderCreateWithCFData(data); CFRelease(data); } else - provider = CGDataProviderCreateWithData(NULL, surface->bits + offset, size, NULL); + provider = CGDataProviderCreateWithData(NULL, (UInt8 *)window_surface->color_bits + offset, size, NULL);
alphaInfo = surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect), diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 752a560ddec..3447e151329 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -45,7 +45,6 @@ struct wayland_window_surface struct window_surface header; struct wayland_surface *wayland_surface; struct wayland_buffer_queue *wayland_buffer_queue; - void *bits; BITMAPINFO info; };
@@ -220,7 +219,7 @@ static void *wayland_window_surface_get_bitmap_info(struct window_surface *windo /* We don't store any additional information at the end of our BITMAPINFO, so * just copy the structure itself. */ memcpy(info, &surface->info, sizeof(*info)); - return surface->bits; + return window_surface->color_bits; }
/*********************************************************************** @@ -308,17 +307,15 @@ static void copy_pixel_region(char *src_pixels, RECT *src_rect, }
/********************************************************************** - * wayland_window_surface_copy_to_buffer + * wayland_shm_buffer_copy_data */ -static void wayland_window_surface_copy_to_buffer(struct wayland_window_surface *wws, - struct wayland_shm_buffer *buffer, - HRGN region) +static void wayland_shm_buffer_copy_data(struct wayland_shm_buffer *buffer, + char *bits, RECT *rect, + HRGN region) { - RECT wws_rect = {0, 0, wws->info.bmiHeader.biWidth, - abs(wws->info.bmiHeader.biHeight)}; RECT buffer_rect = {0, 0, buffer->width, buffer->height}; - TRACE("wws=%p buffer=%p\n", wws, buffer); - copy_pixel_region(wws->bits, &wws_rect, buffer->map_data, &buffer_rect, region); + TRACE("buffer=%p bits=%p rect=%s\n", buffer, bits, wine_dbgstr_rect(rect)); + copy_pixel_region(bits, rect, buffer->map_data, &buffer_rect, region); }
static void wayland_shm_buffer_copy(struct wayland_shm_buffer *src, @@ -396,7 +393,8 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, copy_from_window_region = shm_buffer->damage_region; }
- wayland_window_surface_copy_to_buffer(wws, shm_buffer, copy_from_window_region); + wayland_shm_buffer_copy_data(shm_buffer, window_surface->color_bits, + &window_surface->rect, copy_from_window_region);
pthread_mutex_lock(&wws->wayland_surface->mutex); if (wayland_surface_reconfigure(wws->wayland_surface)) @@ -437,7 +435,7 @@ static void wayland_window_surface_destroy(struct window_surface *window_surface
if (wws->wayland_buffer_queue) wayland_buffer_queue_destroy(wws->wayland_buffer_queue); - free(wws->bits); + free(window_surface->color_bits); free(wws); }
@@ -473,11 +471,11 @@ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect wws->info.bmiHeader.biPlanes = 1; wws->info.bmiHeader.biSizeImage = width * height * 4;
- if (!(wws->bits = malloc(wws->info.bmiHeader.biSizeImage))) + if (!(wws->header.color_bits = malloc(wws->info.bmiHeader.biSizeImage))) goto failed;
- TRACE("created %p hwnd %p %s bits [%p,%p)\n", wws, hwnd, wine_dbgstr_rect(rect), - wws->bits, (char *)wws->bits + wws->info.bmiHeader.biSizeImage); + TRACE("created %p hwnd %p %s color_bits [%p,%p)\n", wws, hwnd, wine_dbgstr_rect(rect), + wws->header.color_bits, (char *)wws->header.color_bits + wws->info.bmiHeader.biSizeImage);
return &wws->header;
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index df8fc8f1257..db175938c89 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1581,7 +1581,6 @@ struct x11drv_window_surface BOOL is_argb; DWORD alpha_bits; COLORREF color_key; - void *bits; #ifdef HAVE_LIBXXSHM XShmSegmentInfo shminfo; #endif @@ -1627,7 +1626,7 @@ static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len ) /*********************************************************************** * update_surface_region */ -static void update_surface_region( struct x11drv_window_surface *surface ) +static void update_surface_region( struct x11drv_window_surface *surface, const void *color_bits ) { #ifdef HAVE_LIBXSHAPE char buffer[4096]; @@ -1657,7 +1656,7 @@ static void update_surface_region( struct x11drv_window_surface *surface ) { case 16: { - WORD *bits = surface->bits; + const WORD *bits = color_bits; int stride = (width + 1) & ~1; UINT mask = masks[0] | masks[1] | masks[2];
@@ -1676,7 +1675,7 @@ static void update_surface_region( struct x11drv_window_surface *surface ) } case 24: { - BYTE *bits = surface->bits; + 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) @@ -1702,7 +1701,7 @@ static void update_surface_region( struct x11drv_window_surface *surface ) } case 32: { - DWORD *bits = surface->bits; + const DWORD *bits = color_bits;
if (info->bmiHeader.biCompression == BI_RGB) { @@ -1833,7 +1832,7 @@ static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surfa struct x11drv_window_surface *surface = get_x11_surface( window_surface );
memcpy( info, &surface->info, get_dib_info_size( &surface->info, DIB_RGB_COLORS )); - return surface->bits; + return window_surface->color_bits; }
static XRectangle *xrectangles_from_rects( const RECT *rects, UINT count ) @@ -1879,10 +1878,10 @@ 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 ); - unsigned char *src = surface->bits; + unsigned char *src = window_surface->color_bits; unsigned char *dst = (unsigned char *)surface->image->data;
- if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface ); + if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface, window_surface->color_bits );
if (src != dst) { @@ -1926,11 +1925,11 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) { struct x11drv_window_surface *surface = get_x11_surface( window_surface );
- TRACE( "freeing %p bits %p\n", surface, surface->bits ); + 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 != surface->bits) free( surface->bits ); + if (surface->image->data != window_surface->color_bits) free( window_surface->color_bits ); #ifdef HAVE_LIBXXSHM if (surface->shminfo.shmid != -1) { @@ -2004,13 +2003,13 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn if (surface->byteswap || format->bits_per_pixel == 4 || format->bits_per_pixel == 8) { /* allocate separate surface bits if byte swapping or palette mapping is required */ - if (!(surface->bits = calloc( 1, surface->info.bmiHeader.biSizeImage ))) + if (!(surface->header.color_bits = calloc( 1, surface->info.bmiHeader.biSizeImage ))) goto failed; } - else surface->bits = surface->image->data; + else surface->header.color_bits = surface->image->data;
- TRACE( "created %p for %lx %s bits %p-%p image %p\n", surface, window, wine_dbgstr_rect(rect), - surface->bits, (char *)surface->bits + surface->info.bmiHeader.biSizeImage, + 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 + surface->info.bmiHeader.biSizeImage, surface->image->data );
return &surface->header; @@ -2033,7 +2032,7 @@ void set_surface_color_key( struct window_surface *window_surface, COLORREF colo window_surface_lock( window_surface ); prev = surface->color_key; set_color_key( surface, color_key ); - if (surface->color_key != prev) update_surface_region( surface ); + if (surface->color_key != prev) update_surface_region( surface, window_surface->color_bits ); window_surface_unlock( window_surface ); }
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 588930f9e01..07d29c9b399 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -225,10 +225,11 @@ struct window_surface HWND hwnd; /* window the surface was created for */ RECT rect; /* constant, no locking needed */
- pthread_mutex_t mutex; - RECT bounds; /* dirty area rect, requires locking */ + pthread_mutex_t mutex; /* mutex needed for any field below */ + RECT bounds; /* dirty area rectangle */ HRGN clip_region; /* visible region of the surface, fully visible if 0 */ DWORD draw_start_ticks; /* start ticks of fresh draw */ + void *color_bits; /* pixel bits of the surface color */ /* driver-specific fields here */ };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 40 +++++++++++++++++++-------- dlls/wineandroid.drv/window.c | 22 +++++++++------ dlls/winemac.drv/surface.c | 35 +++++++++++------------ dlls/winewayland.drv/window_surface.c | 23 ++++++++------- dlls/winex11.drv/bitblt.c | 30 +++++++++++--------- include/wine/gdi_driver.h | 3 +- 6 files changed, 90 insertions(+), 63 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 6bb090cedcf..8e6fab478d1 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -156,6 +156,8 @@ static const struct window_surface_funcs offscreen_window_surface_funcs =
void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struct window_surface **surface ) { + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *info = (BITMAPINFO *)buffer; struct offscreen_window_surface *impl; SIZE_T size; RECT surface_rect = *visible_rect; @@ -175,20 +177,23 @@ void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struc } else if (*surface) window_surface_release( *surface );
+ memset( info, 0, sizeof(*info) ); + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = surface_rect.right; + info->bmiHeader.biHeight = -surface_rect.bottom; /* top-down */ + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biSizeImage = get_dib_image_size( info ); + info->bmiHeader.biCompression = BI_RGB; + /* create a new window surface */ *surface = NULL; - size = surface_rect.right * surface_rect.bottom * 4; + size = info->bmiHeader.biSizeImage; if (!(impl = calloc(1, offsetof( struct offscreen_window_surface, info.bmiColors[0] ) + size))) return; - window_surface_init( &impl->header, &offscreen_window_surface_funcs, hwnd, &surface_rect ); + window_surface_init( &impl->header, &offscreen_window_surface_funcs, hwnd, info, 0 );
impl->header.color_bits = (char *)&impl->info.bmiColors[0]; - impl->info.bmiHeader.biSize = sizeof( impl->info ); - impl->info.bmiHeader.biWidth = surface_rect.right; - impl->info.bmiHeader.biHeight = surface_rect.bottom; - impl->info.bmiHeader.biPlanes = 1; - impl->info.bmiHeader.biBitCount = 32; - impl->info.bmiHeader.biCompression = BI_RGB; - impl->info.bmiHeader.biSizeImage = size; + impl->info = *info;
TRACE( "created window surface %p\n", &impl->header );
@@ -197,14 +202,27 @@ void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struc
/* window surface common helpers */
-W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect ) +W32KAPI BOOL window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, + HWND hwnd, BITMAPINFO *info, HBITMAP bitmap ) { + struct bitblt_coords coords = {0}; + struct gdi_image_bits bits; + BITMAPOBJ *bmp; + surface->funcs = funcs; surface->ref = 1; surface->hwnd = hwnd; - surface->rect = *rect; + SetRect( &surface->rect, 0, 0, info->bmiHeader.biWidth, abs( info->bmiHeader.biHeight ) ); pthread_mutex_init( &surface->mutex, NULL ); reset_bounds( &surface->bounds ); + + if (!bitmap) return TRUE; + if (!(bmp = GDI_GetObjPtr( bitmap, NTGDI_OBJ_BITMAP ))) return FALSE; + get_image_from_bitmap( bmp, info, &bits, &coords ); + surface->color_bits = bits.ptr; + GDI_ReleaseObj( bitmap ); + + return TRUE; }
W32KAPI void window_surface_add_ref( struct window_surface *surface ) diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 657a5ff62cc..83e39528273 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -781,26 +781,30 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, { struct android_window_surface *surface; int width = rect->right - rect->left, height = rect->bottom - rect->top; + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *info = (BITMAPINFO *)buffer; + + memset( info, 0, sizeof(*info) ); + set_color_info( info, src_alpha ); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = -height; /* top-down */ + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biSizeImage = get_dib_image_size( info );
surface = calloc( 1, FIELD_OFFSET( struct android_window_surface, info.bmiColors[3] )); if (!surface) return NULL; - window_surface_init( &surface->header, &android_surface_funcs, hwnd, rect ); - - set_color_info( &surface->info, src_alpha ); - surface->info.bmiHeader.biWidth = width; - surface->info.bmiHeader.biHeight = -height; /* top-down */ - surface->info.bmiHeader.biPlanes = 1; - surface->info.bmiHeader.biSizeImage = get_dib_image_size( &surface->info ); + if (!window_surface_init( &surface->header, &android_surface_funcs, hwnd, info, 0 )) goto failed; + memcpy( &surface->info, info, get_dib_info_size( info, DIB_RGB_COLORS ) );
surface->window = get_ioctl_window( hwnd ); surface->alpha = alpha; set_color_key( surface, color_key );
- if (!(surface->header.color_bits = malloc( surface->info.bmiHeader.biSizeImage ))) + if (!(surface->header.color_bits = malloc( info->bmiHeader.biSizeImage ))) goto failed;
TRACE( "created %p hwnd %p %s color_bits %p-%p\n", surface, hwnd, wine_dbgstr_rect(rect), - surface->header.color_bits, (char *)surface->header.color_bits + surface->info.bmiHeader.biSizeImage ); + surface->header.color_bits, (char *)surface->header.color_bits + info->bmiHeader.biSizeImage );
return &surface->header;
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index a34df22397a..16e1629f993 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -133,37 +133,34 @@ struct window_surface *create_surface(HWND hwnd, macdrv_window window, const REC { struct macdrv_window_surface *surface; int width = rect->right - rect->left, height = rect->bottom - rect->top; - DWORD *colors; DWORD window_background; + char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *info = (BITMAPINFO *)buffer; + + memset(info, 0, sizeof(*info)); + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = -height; /* top-down */ + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biSizeImage = get_dib_image_size(info); + info->bmiHeader.biCompression = BI_RGB;
surface = calloc(1, FIELD_OFFSET(struct macdrv_window_surface, info.bmiColors[3])); if (!surface) return NULL; - window_surface_init(&surface->header, &macdrv_surface_funcs, hwnd, rect); - - surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); - surface->info.bmiHeader.biWidth = width; - surface->info.bmiHeader.biHeight = -height; /* top-down */ - surface->info.bmiHeader.biPlanes = 1; - surface->info.bmiHeader.biBitCount = 32; - surface->info.bmiHeader.biSizeImage = get_dib_image_size(&surface->info); - surface->info.bmiHeader.biCompression = BI_RGB; - surface->info.bmiHeader.biClrUsed = 0; - - colors = (DWORD *)((char *)&surface->info + surface->info.bmiHeader.biSize); - colors[0] = 0x00ff0000; - colors[1] = 0x0000ff00; - colors[2] = 0x000000ff; + if (!window_surface_init(&surface->header, &macdrv_surface_funcs, hwnd, info, 0)) goto failed; + memcpy(&surface->info, info, offsetof(BITMAPINFO, bmiColors[3]));
surface->window = window; if (old_surface) surface->header.bounds = old_surface->bounds; surface->use_alpha = use_alpha; - surface->header.color_bits = malloc(surface->info.bmiHeader.biSizeImage); + surface->header.color_bits = malloc(info->bmiHeader.biSizeImage); if (!surface->header.color_bits) goto failed; window_background = macdrv_window_background_color(); - memset_pattern4(surface->header.color_bits, &window_background, surface->info.bmiHeader.biSizeImage); + memset_pattern4(surface->header.color_bits, &window_background, info->bmiHeader.biSizeImage);
TRACE("created %p for %p %s color_bits %p-%p\n", surface, window, wine_dbgstr_rect(rect), - surface->header.color_bits, (char *)surface->header.color_bits + surface->info.bmiHeader.biSizeImage); + surface->header.color_bits, (char *)surface->header.color_bits + info->bmiHeader.biSizeImage);
return &surface->header;
diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 3447e151329..636c681a25a 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -452,24 +452,27 @@ static const struct window_surface_funcs wayland_window_surface_funcs = */ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect) { + char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *info = (BITMAPINFO *)buffer; struct wayland_window_surface *wws; int width = rect->right - rect->left; int height = rect->bottom - rect->top;
TRACE("hwnd %p rect %s\n", hwnd, wine_dbgstr_rect(rect));
+ memset(info, 0, sizeof(*info)); + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = -height; /* top-down */ + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biSizeImage = width * height * 4; + info->bmiHeader.biCompression = BI_RGB; + wws = calloc(1, sizeof(*wws)); if (!wws) return NULL; - window_surface_init(&wws->header, &wayland_window_surface_funcs, hwnd, rect); - - wws->info.bmiHeader.biSize = sizeof(wws->info.bmiHeader); - wws->info.bmiHeader.biClrUsed = 0; - wws->info.bmiHeader.biBitCount = 32; - wws->info.bmiHeader.biCompression = BI_RGB; - wws->info.bmiHeader.biWidth = width; - wws->info.bmiHeader.biHeight = -height; /* top-down */ - wws->info.bmiHeader.biPlanes = 1; - wws->info.bmiHeader.biSizeImage = width * height * 4; + if (!window_surface_init(&wws->header, &wayland_window_surface_funcs, hwnd, info, 0)) goto failed; + wws->info = *info;
if (!(wws->header.color_bits = malloc(wws->info.bmiHeader.biSizeImage))) goto failed; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index db175938c89..74ba28cfc37 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1961,24 +1961,28 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn COLORREF color_key, BOOL use_alpha ) { const XPixmapFormatValues *format = pixmap_formats[vis->depth]; + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *info = (BITMAPINFO *)buffer; 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;
+ memset( info, 0, sizeof(*info) ); + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = -height; /* top-down */ + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = format->bits_per_pixel; + 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; - window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, rect ); - - surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); - surface->info.bmiHeader.biWidth = width; - surface->info.bmiHeader.biHeight = -height; /* top-down */ - surface->info.bmiHeader.biPlanes = 1; - surface->info.bmiHeader.biBitCount = format->bits_per_pixel; - surface->info.bmiHeader.biSizeImage = get_dib_image_size( &surface->info ); - if (format->bits_per_pixel > 8) set_color_info( vis, &surface->info, use_alpha ); + 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 ) );
surface->window = window; - surface->is_argb = (use_alpha && vis->depth == 32 && surface->info.bmiHeader.biCompression == BI_RGB); + surface->is_argb = (use_alpha && vis->depth == 32 && info->bmiHeader.biCompression == BI_RGB); set_color_key( surface, color_key );
#ifdef HAVE_LIBXXSHM @@ -1989,7 +1993,7 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn 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( surface->info.bmiHeader.biSizeImage ); + surface->image->data = malloc( info->bmiHeader.biSizeImage ); if (!surface->image->data) goto failed; }
@@ -2003,13 +2007,13 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn if (surface->byteswap || format->bits_per_pixel == 4 || format->bits_per_pixel == 8) { /* allocate separate surface bits if byte swapping or palette mapping is required */ - if (!(surface->header.color_bits = calloc( 1, surface->info.bmiHeader.biSizeImage ))) + if (!(surface->header.color_bits = calloc( 1, info->bmiHeader.biSizeImage ))) goto failed; } else surface->header.color_bits = surface->image->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 + surface->info.bmiHeader.biSizeImage, + surface->header.color_bits, (char *)surface->header.color_bits + info->bmiHeader.biSizeImage, surface->image->data );
return &surface->header; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 07d29c9b399..556e33d1fa2 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -233,7 +233,8 @@ struct window_surface /* driver-specific fields here */ };
-W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect ); +W32KAPI BOOL window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, + HWND hwnd, BITMAPINFO *info, HBITMAP bitmap ); W32KAPI void window_surface_add_ref( struct window_surface *surface ); W32KAPI void window_surface_release( struct window_surface *surface ); W32KAPI void window_surface_lock( struct window_surface *surface );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/bitblt.c | 75 +++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 22 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 74ba28cfc37..f23cda3bfd2 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1570,6 +1570,11 @@ DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo return ret; }
+#ifdef HAVE_X11_EXTENSIONS_XSHM_H +typedef XShmSegmentInfo x11drv_xshm_info_t; +#else +typedef struct { int shmid; } x11drv_xshm_info_t; +#endif
struct x11drv_window_surface { @@ -1581,9 +1586,7 @@ struct x11drv_window_surface BOOL is_argb; DWORD alpha_bits; COLORREF color_key; -#ifdef HAVE_LIBXXSHM - XShmSegmentInfo shminfo; -#endif + x11drv_xshm_info_t shminfo; BITMAPINFO info; /* variable size, must be last */ };
@@ -1786,7 +1789,7 @@ static int xshm_error_handler( Display *display, XErrorEvent *event, void *arg ) return 1; /* FIXME: should check event contents */ }
-static XImage *create_shm_image( const XVisualInfo *vis, int width, int height, XShmSegmentInfo *shminfo ) +static XImage *create_shm_image( const XVisualInfo *vis, int width, int height, x11drv_xshm_info_t *shminfo ) { XImage *image;
@@ -1822,6 +1825,48 @@ failed: XDestroyImage( image ); return NULL; } + +static BOOL destroy_shm_image( XImage *image, x11drv_xshm_info_t *shminfo ) +{ + if (shminfo->shmid == -1) return FALSE; + + XShmDetach( gdi_display, shminfo ); + shmdt( shminfo->shmaddr ); + + return TRUE; +} + +static BOOL put_shm_image( XImage *image, x11drv_xshm_info_t *shminfo, Window window, + GC gc, const RECT *rect, const RECT *dirty ) +{ + if (shminfo->shmid == -1) return FALSE; + + XShmPutImage( gdi_display, window, gc, image, dirty->left, + dirty->top, rect->left + dirty->left, rect->top + dirty->top, + dirty->right - dirty->left, dirty->bottom - dirty->top, False ); + + return TRUE; +} + +#else /* HAVE_LIBXXSHM */ + +static XImage *create_shm_image( const XVisualInfo *vis, int width, int height, x11drv_xshm_info_t *shminfo ) +{ + shminfo->shmid = -1; + return NULL; +} + +static BOOL destroy_shm_image( XImage *image ) +{ + return FALSE; +} + +static BOOL put_shm_image( XImage *image, x11drv_xshm_info_t *shminfo, Window window, + GC gc, const RECT *rect, const RECT *dirty ) +{ + return FALSE; +} + #endif /* HAVE_LIBXXSHM */
/*********************************************************************** @@ -1903,16 +1948,11 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R ptr[x] |= surface->alpha_bits; }
-#ifdef HAVE_LIBXXSHM - if (surface->shminfo.shmid != -1) - XShmPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, - dirty->top, rect->left + dirty->left, rect->top + dirty->top, - dirty->right - dirty->left, dirty->bottom - dirty->top, False ); - else -#endif + if (!put_shm_image( surface->image, &surface->shminfo, surface->window, surface->gc, rect, dirty )) XPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, dirty->top, rect->left + dirty->left, rect->top + dirty->top, dirty->right - dirty->left, dirty->bottom - dirty->top ); + XFlush( gdi_display );
return TRUE; @@ -1930,15 +1970,8 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) 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 ); + if (!destroy_shm_image( surface->image, &surface->shminfo )) + free( surface->image->data ); surface->image->data = NULL; XDestroyImage( surface->image ); } @@ -1985,10 +2018,8 @@ 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 );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/bitblt.c | 90 +++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 28 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index f23cda3bfd2..dead700d63c 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1576,17 +1576,22 @@ typedef XShmSegmentInfo x11drv_xshm_info_t; typedef struct { int shmid; } x11drv_xshm_info_t; #endif
+struct x11drv_image +{ + XImage *ximage; /* XImage used for X11 drawing */ + x11drv_xshm_info_t shminfo; /* XSHM extension info */ +}; + 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; - x11drv_xshm_info_t shminfo; BITMAPINFO info; /* variable size, must be last */ };
@@ -1869,6 +1874,37 @@ static BOOL put_shm_image( XImage *image, x11drv_xshm_info_t *shminfo, Window wi
#endif /* HAVE_LIBXXSHM */
+static void x11drv_image_destroy( struct x11drv_image *image ) +{ + if (!destroy_shm_image( image->ximage, &image->shminfo )) + free( image->ximage->data ); + + image->ximage->data = NULL; + XDestroyImage( image->ximage ); + free( image ); +} + +static struct x11drv_image *x11drv_image_create( const BITMAPINFO *info, const XVisualInfo *vis ) +{ + UINT width = info->bmiHeader.biWidth, height = abs( info->bmiHeader.biHeight ); + struct x11drv_image *image; + + if (!(image = calloc( 1, sizeof(*image) ))) return NULL; + + if (!(image->ximage = create_shm_image( vis, width, height, &image->shminfo ))) + { + if (!(image->ximage = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, + 0, NULL, width, height, 32, 0 ))) goto failed; + if (!(image->ximage->data = malloc( info->bmiHeader.biSizeImage ))) goto failed; + } + + return image; + +failed: + x11drv_image_destroy( image ); + return NULL; +} + /*********************************************************************** * x11drv_surface_get_bitmap_info */ @@ -1923,15 +1959,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; @@ -1940,7 +1977,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) @@ -1948,8 +1985,8 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R ptr[x] |= surface->alpha_bits; }
- if (!put_shm_image( surface->image, &surface->shminfo, surface->window, surface->gc, rect, dirty )) - XPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, + if (!put_shm_image( ximage, &surface->image->shminfo, surface->window, surface->gc, rect, dirty )) + 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 );
@@ -1969,11 +2006,9 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) if (surface->gc) XFreeGC( gdi_display, surface->gc ); if (surface->image) { - if (surface->image->data != window_surface->color_bits) free( window_surface->color_bits ); - if (!destroy_shm_image( surface->image, &surface->shminfo )) - free( surface->image->data ); - surface->image->data = NULL; - XDestroyImage( surface->image ); + if (surface->image->ximage->data != window_surface->color_bits) + free( window_surface->color_bits ); + x11drv_image_destroy( surface->image ); }
free( surface ); @@ -1999,6 +2034,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;
memset( info, 0, sizeof(*info) ); info->bmiHeader.biSize = sizeof(info->bmiHeader); @@ -2009,8 +2046,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 ) );
@@ -2018,19 +2062,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 );
- surface->image = create_shm_image( vis, width, height, &surface->shminfo ); - if (!surface->image) - { - 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); @@ -2041,11 +2075,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;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/bitblt.c | 77 +++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 19 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index dead700d63c..fe71e4de18f 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1588,6 +1588,7 @@ struct x11drv_window_surface Window window; GC gc; struct x11drv_image *image; + HBITMAP bitmap; /* bitmap exposed to win32u */ BOOL byteswap; BOOL is_argb; DWORD alpha_bits; @@ -1874,6 +1875,29 @@ static BOOL put_shm_image( XImage *image, x11drv_xshm_info_t *shminfo, Window wi
#endif /* HAVE_LIBXXSHM */
+static UINT get_dib_d3dddifmt( const BITMAPINFO *info ) +{ + if (info->bmiHeader.biCompression == BI_RGB) + { + if (info->bmiHeader.biBitCount == 8) return D3DDDIFMT_P8; + if (info->bmiHeader.biBitCount == 24) return D3DDDIFMT_R8G8B8; + if (info->bmiHeader.biBitCount == 32) return D3DDDIFMT_A8R8G8B8; + return D3DDDIFMT_UNKNOWN; + } + + if (info->bmiHeader.biCompression == BI_BITFIELDS) + { + DWORD *colors = (DWORD *)info->bmiColors; + if (info->bmiHeader.biBitCount != 16) return D3DDDIFMT_UNKNOWN; + if (colors[0] == 0x0000f800 && colors[1] == 0x000007e0 && colors[2] == 0x0000001f) return D3DDDIFMT_R5G6B5; + if (colors[0] == 0x00007c00 && colors[1] == 0x000003e0 && colors[2] == 0x0000001f) return D3DDDIFMT_A1R5G5B5; + if (colors[0] == 0x00000f00 && colors[1] == 0x000000f0 && colors[2] == 0x0000000f) return D3DDDIFMT_A4R4G4B4; + return D3DDDIFMT_UNKNOWN; + } + + return D3DDDIFMT_UNKNOWN; +} + static void x11drv_image_destroy( struct x11drv_image *image ) { if (!destroy_shm_image( image->ximage, &image->shminfo )) @@ -2004,13 +2028,8 @@ 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->ximage->data != window_surface->color_bits) - free( window_surface->color_bits ); - x11drv_image_destroy( surface->image ); - } - + if (surface->image) x11drv_image_destroy( surface->image ); + if (surface->bitmap) NtGdiDeleteObjectApp( surface->bitmap ); free( surface ); }
@@ -2035,6 +2054,9 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn 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; + D3DDDIFORMAT d3d_format; + HBITMAP bitmap = 0; + BOOL byteswap; UINT size;
memset( info, 0, sizeof(*info) ); @@ -2048,14 +2070,40 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn
size = FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] ); if (!(image = x11drv_image_create( info, vis ))) return NULL; - if (!(surface = calloc( 1, size ))) + + /* wrap the XImage data in a HBITMAP if we can write to the surface pixels directly */ + if (!(byteswap = image_needs_byteswap( image->ximage, is_r8g8b8( vis ), info->bmiHeader.biBitCount )) && + info->bmiHeader.biBitCount > 8 && (d3d_format = get_dib_d3dddifmt( info ))) + { + D3DKMT_CREATEDCFROMMEMORY desc = + { + .Width = info->bmiHeader.biWidth, + .Height = info->bmiHeader.biHeight, + .Pitch = info->bmiHeader.biWidth * info->bmiHeader.biBitCount / 8, + .Format = d3d_format, + .pMemory = image->ximage->data, + }; + + if (!NtGdiDdDDICreateDCFromMemory( &desc )) + { + bitmap = desc.hBitmap; + NtGdiDeleteObjectApp( desc.hDc ); + } + } + + if (!bitmap) bitmap = NtGdiCreateDIBSection( 0, NULL, 0, info, DIB_RGB_COLORS, 0, 0, 0, NULL ); + + if (!bitmap || !(surface = calloc( 1, size ))) { + if (bitmap) NtGdiDeleteObjectApp( bitmap ); x11drv_image_destroy( image ); return NULL; } surface->image = image; + surface->bitmap = bitmap; + surface->byteswap = byteswap;
- if (!window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, info, 0 )) goto failed; + if (!window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, info, bitmap )) goto failed; memcpy( &surface->info, info, get_dib_info_size( info, DIB_RGB_COLORS ) );
surface->window = window; @@ -2064,20 +2112,11 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn
surface->gc = XCreateGC( gdi_display, window, 0, NULL ); XSetSubwindowMode( gdi_display, surface->gc, IncludeInferiors ); - 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);
- if (surface->byteswap || format->bits_per_pixel == 4 || format->bits_per_pixel == 8) - { - /* allocate separate surface bits if byte swapping or palette mapping is required */ - if (!(surface->header.color_bits = calloc( 1, info->bmiHeader.biSizeImage ))) - goto failed; - } - 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), + TRACE( "created %p for %lx %s 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->ximage->data );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 11 ++++------- dlls/wineandroid.drv/window.c | 8 ++------ dlls/winemac.drv/surface.c | 6 ++---- dlls/winewayland.drv/window_surface.c | 6 +----- dlls/winex11.drv/bitblt.c | 9 ++------- include/wine/gdi_driver.h | 3 ++- 6 files changed, 13 insertions(+), 30 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 8e6fab478d1..f6726b49aa1 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -159,7 +159,6 @@ void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struc char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; struct offscreen_window_surface *impl; - SIZE_T size; RECT surface_rect = *visible_rect;
TRACE( "hwnd %p, visible_rect %s, surface %p.\n", hwnd, wine_dbgstr_rect( visible_rect ), surface ); @@ -188,11 +187,8 @@ void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struc
/* create a new window surface */ *surface = NULL; - size = info->bmiHeader.biSizeImage; - if (!(impl = calloc(1, offsetof( struct offscreen_window_surface, info.bmiColors[0] ) + size))) return; + if (!(impl = calloc(1, sizeof(*impl)))) return; window_surface_init( &impl->header, &offscreen_window_surface_funcs, hwnd, info, 0 ); - - impl->header.color_bits = (char *)&impl->info.bmiColors[0]; impl->info = *info;
TRACE( "created window surface %p\n", &impl->header ); @@ -216,8 +212,8 @@ W32KAPI BOOL window_surface_init( struct window_surface *surface, const struct w pthread_mutex_init( &surface->mutex, NULL ); reset_bounds( &surface->bounds );
- if (!bitmap) return TRUE; - if (!(bmp = GDI_GetObjPtr( bitmap, NTGDI_OBJ_BITMAP ))) return FALSE; + if (!bitmap) bitmap = NtGdiCreateDIBSection( 0, NULL, 0, info, DIB_RGB_COLORS, 0, 0, 0, NULL ); + if (!(surface->color_bitmap = bitmap) || !(bmp = GDI_GetObjPtr( bitmap, NTGDI_OBJ_BITMAP ))) return FALSE; get_image_from_bitmap( bmp, info, &bits, &coords ); surface->color_bits = bits.ptr; GDI_ReleaseObj( bitmap ); @@ -237,6 +233,7 @@ W32KAPI void window_surface_release( struct window_surface *surface ) { if (surface != &dummy_surface) pthread_mutex_destroy( &surface->mutex ); if (surface->clip_region) NtGdiDeleteObjectApp( surface->clip_region ); + if (surface->color_bitmap) NtGdiDeleteObjectApp( surface->color_bitmap ); surface->funcs->destroy( surface ); } } diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 83e39528273..fa7b87522c5 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -732,11 +732,10 @@ static void android_surface_destroy( struct window_surface *window_surface ) { struct android_window_surface *surface = get_android_surface( window_surface );
- TRACE( "freeing %p bits %p\n", surface, window_surface->color_bits ); + TRACE( "freeing %p\n", surface );
free( surface->clip_rects ); release_ioctl_window( surface->window ); - free( window_surface->color_bits ); free( surface ); }
@@ -800,10 +799,7 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, surface->alpha = alpha; set_color_key( surface, color_key );
- if (!(surface->header.color_bits = malloc( info->bmiHeader.biSizeImage ))) - goto failed; - - TRACE( "created %p hwnd %p %s color_bits %p-%p\n", surface, hwnd, wine_dbgstr_rect(rect), + TRACE( "created %p hwnd %p %s bits %p-%p\n", surface, hwnd, wine_dbgstr_rect(rect), surface->header.color_bits, (char *)surface->header.color_bits + info->bmiHeader.biSizeImage );
return &surface->header; diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 16e1629f993..82b7a382ec4 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -106,8 +106,7 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) { struct macdrv_window_surface *surface = get_mac_surface(window_surface);
- TRACE("freeing %p bits %p\n", surface, window_surface->color_bits); - free(window_surface->color_bits); + TRACE("freeing %p\n", surface); free(surface); }
@@ -154,8 +153,7 @@ struct window_surface *create_surface(HWND hwnd, macdrv_window window, const REC surface->window = window; if (old_surface) surface->header.bounds = old_surface->bounds; surface->use_alpha = use_alpha; - surface->header.color_bits = malloc(info->bmiHeader.biSizeImage); - if (!surface->header.color_bits) goto failed; + window_background = macdrv_window_background_color(); memset_pattern4(surface->header.color_bits, &window_background, info->bmiHeader.biSizeImage);
diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 636c681a25a..c0b516c9288 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -435,7 +435,6 @@ static void wayland_window_surface_destroy(struct window_surface *window_surface
if (wws->wayland_buffer_queue) wayland_buffer_queue_destroy(wws->wayland_buffer_queue); - free(window_surface->color_bits); free(wws); }
@@ -474,10 +473,7 @@ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect if (!window_surface_init(&wws->header, &wayland_window_surface_funcs, hwnd, info, 0)) goto failed; wws->info = *info;
- if (!(wws->header.color_bits = malloc(wws->info.bmiHeader.biSizeImage))) - goto failed; - - TRACE("created %p hwnd %p %s color_bits [%p,%p)\n", wws, hwnd, wine_dbgstr_rect(rect), + TRACE("created %p hwnd %p %s bits [%p,%p)\n", wws, hwnd, wine_dbgstr_rect(rect), wws->header.color_bits, (char *)wws->header.color_bits + wws->info.bmiHeader.biSizeImage);
return &wws->header; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index fe71e4de18f..ec6250048cf 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1588,7 +1588,6 @@ struct x11drv_window_surface Window window; GC gc; struct x11drv_image *image; - HBITMAP bitmap; /* bitmap exposed to win32u */ BOOL byteswap; BOOL is_argb; DWORD alpha_bits; @@ -2026,10 +2025,9 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) { struct x11drv_window_surface *surface = get_x11_surface( window_surface );
- TRACE( "freeing %p bits %p\n", surface, window_surface->color_bits ); + TRACE( "freeing %p\n", surface ); if (surface->gc) XFreeGC( gdi_display, surface->gc ); if (surface->image) x11drv_image_destroy( surface->image ); - if (surface->bitmap) NtGdiDeleteObjectApp( surface->bitmap ); free( surface ); }
@@ -2091,16 +2089,13 @@ struct window_surface *create_surface( HWND hwnd, Window window, const XVisualIn } }
- if (!bitmap) bitmap = NtGdiCreateDIBSection( 0, NULL, 0, info, DIB_RGB_COLORS, 0, 0, 0, NULL ); - - if (!bitmap || !(surface = calloc( 1, size ))) + if (!(surface = calloc( 1, size ))) { if (bitmap) NtGdiDeleteObjectApp( bitmap ); x11drv_image_destroy( image ); return NULL; } surface->image = image; - surface->bitmap = bitmap; surface->byteswap = byteswap;
if (!window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, info, bitmap )) goto failed; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 556e33d1fa2..ce954a7f4d8 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -229,7 +229,8 @@ struct window_surface RECT bounds; /* dirty area rectangle */ HRGN clip_region; /* visible region of the surface, fully visible if 0 */ DWORD draw_start_ticks; /* start ticks of fresh draw */ - void *color_bits; /* pixel bits of the surface color */ + HBITMAP color_bitmap; /* bitmap for the surface colors */ + void *color_bits; /* pixel bits of the color bitmap */ /* driver-specific fields here */ };
v3: Zero BITMAPINFO structs, fix a typo in the offscreen surface biSizeImage, simplify XSHM extension usage using a dummy struct and dummy helpers when it isn't available.
Simplify the winex11 memory management by always allocating XImage data when not using XSHM, and then wrapping the XImage data in a D3DDDI bitmap in both cases.
The D3DDDI bitmap should support all the common formats for which we can write directly to the surface pixels. Other case involves a bitmap allocated on the win32u side and copies in winex11 surface flush.