Alexandre Julliard : winex11: Use the XShm extension to copy window surfaces.

Alexandre Julliard julliard at winehq.org
Wed Oct 3 13:20:36 CDT 2012


Module: wine
Branch: master
Commit: 5a9de7a4989dcf08914b5efd3152248a70be4548
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5a9de7a4989dcf08914b5efd3152248a70be4548

Author: Alexandre Julliard <julliard at 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;
 




More information about the wine-cvs mailing list