Module: wine Branch: master Commit: 5a9de7a4989dcf08914b5efd3152248a70be4548 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5a9de7a4989dcf08914b5efd31...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Oct 3 15:26:08 2012 +0200
winex11: Use the XShm extension to copy window surfaces.
---
dlls/winex11.drv/bitblt.c | 100 +++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 92 insertions(+), 8 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index b37007e..e1812cd 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -29,9 +29,18 @@ #include <X11/Xlib.h> #include <X11/Xresource.h> #include <X11/Xutil.h> -#ifdef HAVE_LIBXSHAPE +#ifdef HAVE_X11_EXTENSIONS_SHAPE_H #include <X11/extensions/shape.h> #endif +#ifdef HAVE_X11_EXTENSIONS_XSHM_H +# include <X11/extensions/XShm.h> +# ifdef HAVE_SYS_SHM_H +# include <sys/shm.h> +# endif +# ifdef HAVE_SYS_IPC_H +# include <sys/ipc.h> +# endif +#endif
#include "windef.h" #include "winbase.h" @@ -1557,6 +1566,9 @@ struct x11drv_window_surface BOOL is_argb; COLORREF color_key; void *bits; +#ifdef HAVE_LIBXXSHM + XShmSegmentInfo shminfo; +#endif CRITICAL_SECTION crit; BITMAPINFO info; /* variable size, must be last */ }; @@ -1750,6 +1762,50 @@ static void set_color_key( struct x11drv_window_surface *surface, COLORREF key ) get_color_component( GetBValue(key), masks[2] ); }
+#ifdef HAVE_LIBXXSHM +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 ) +{ + XImage *image; + + shminfo->shmid = -1; + image = XShmCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, NULL, shminfo, width, height ); + if (!image) return NULL; + if (image->bytes_per_line & 3) goto failed; /* we need 32-bit alignment */ + + shminfo->shmid = shmget( IPC_PRIVATE, image->bytes_per_line * height, IPC_CREAT | 0700 ); + if (shminfo->shmid == -1) goto failed; + + shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 ); + if (shminfo->shmaddr != (char *)-1) + { + BOOL ok; + + shminfo->readOnly = True; + X11DRV_expect_error( gdi_display, xshm_error_handler, NULL ); + ok = (XShmAttach( gdi_display, shminfo ) != 0); + XSync( gdi_display, False ); + if (!X11DRV_check_error() && ok) + { + image->data = shminfo->shmaddr; + shmctl( shminfo->shmid, IPC_RMID, 0 ); + return image; + } + shmdt( shminfo->shmaddr ); + } + shmctl( shminfo->shmid, IPC_RMID, 0 ); + shminfo->shmid = -1; + +failed: + XDestroyImage( image ); + return NULL; +} +#endif /* HAVE_LIBXXSHM */ + /*********************************************************************** * x11drv_surface_lock */ @@ -1830,6 +1886,19 @@ static void x11drv_surface_flush( struct window_surface *window_surface ) surface->byteswap, mapping, ~0u ); }
+#ifdef HAVE_LIBXXSHM + if (surface->shminfo.shmid != -1) + { + XShmPutImage( gdi_display, surface->window, surface->gc, surface->image, + coords.visrect.left, coords.visrect.top, + surface->header.rect.left + coords.visrect.left, + surface->header.rect.top + coords.visrect.top, + coords.visrect.right - coords.visrect.left, + coords.visrect.bottom - coords.visrect.top, False ); + XSync( gdi_display, False ); + } + else +#endif XPutImage( gdi_display, surface->window, surface->gc, surface->image, coords.visrect.left, coords.visrect.top, surface->header.rect.left + coords.visrect.left, @@ -1853,6 +1922,14 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) if (surface->image) { if (surface->image->data != surface->bits) HeapFree( GetProcessHeap(), 0, surface->bits ); +#ifdef HAVE_LIBXXSHM + if (surface->shminfo.shmid != -1) + { + XShmDetach( gdi_display, &surface->shminfo ); + shmdt( surface->shminfo.shmaddr ); + } + else +#endif HeapFree( GetProcessHeap(), 0, surface->image->data ); surface->image->data = NULL; XDestroyImage( surface->image ); @@ -1905,11 +1982,17 @@ struct window_surface *create_surface( Window window, const XVisualInfo *vis, co set_color_key( surface, color_key ); reset_bounds( &surface->bounds );
- surface->image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL, - width, height, 32, 0 ); - if (!surface->image) goto failed; - surface->image->data = HeapAlloc( GetProcessHeap(), 0, surface->info.bmiHeader.biSizeImage ); - if (!surface->image->data) goto failed; +#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 = HeapAlloc( GetProcessHeap(), 0, surface->info.bmiHeader.biSizeImage ); + if (!surface->image->data) goto failed; + }
surface->gc = XCreateGC( gdi_display, window, 0, NULL ); surface->byteswap = image_needs_byteswap( surface->image, is_r8g8b8(vis), format->bits_per_pixel ); @@ -1923,8 +2006,9 @@ struct window_surface *create_surface( Window window, const XVisualInfo *vis, co } else surface->bits = surface->image->data;
- TRACE( "created %p for %lx %s bits %p-%p\n", surface, window, wine_dbgstr_rect(rect), - surface->bits, (char *)surface->bits + surface->info.bmiHeader.biSizeImage ); + 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, + surface->image->data );
return &surface->header;