[PATCH 5/5] winex11.drv: Add support for XShm pixmaps.
Henri Verbeet
hverbeet at codeweavers.com
Thu Aug 6 01:12:22 CDT 2009
Most of this is "Copyright 2004 Huw Davies for CodeWeavers", I just did a
little bit of integration.
---
dlls/winex11.drv/dib.c | 286 +++++++++++++++++++++++++++++----------------
dlls/winex11.drv/x11drv.h | 8 ++
2 files changed, 193 insertions(+), 101 deletions(-)
diff --git a/dlls/winex11.drv/dib.c b/dlls/winex11.drv/dib.c
index 07ce9e1..effe1a4 100644
--- a/dlls/winex11.drv/dib.c
+++ b/dlls/winex11.drv/dib.c
@@ -62,31 +62,32 @@ static int ximageDepthTable[32];
/* This structure holds the arguments for DIB_SetImageBits() */
typedef struct
{
- X11DRV_PDEVICE *physDev;
- LPCVOID bits;
- XImage *image;
- PALETTEENTRY *palentry;
- int lines;
- DWORD infoWidth;
- WORD depth;
- WORD infoBpp;
- WORD compression;
- RGBQUAD *colorMap;
- int nColorMap;
- Drawable drawable;
- GC gc;
- int xSrc;
- int ySrc;
- int xDest;
- int yDest;
- int width;
- int height;
- DWORD rMask;
- DWORD gMask;
- DWORD bMask;
- BOOL useShm;
- int dibpitch;
- DWORD sizeImage;
+ X11DRV_PDEVICE *physDev;
+ LPCVOID bits;
+ XImage *image;
+ PALETTEENTRY *palentry;
+ int lines;
+ DWORD infoWidth;
+ WORD depth;
+ WORD infoBpp;
+ WORD compression;
+ RGBQUAD *colorMap;
+ int nColorMap;
+ Drawable drawable;
+ GC gc;
+ int xSrc;
+ int ySrc;
+ int xDest;
+ int yDest;
+ int width;
+ int height;
+ DWORD rMask;
+ DWORD gMask;
+ DWORD bMask;
+ enum x11drv_shm_mode shm_mode;
+ int dibpitch;
+ DWORD sizeImage;
+ X_PHYSBITMAP *physBitmap;
} X11DRV_DIB_IMAGEBITS_DESCR;
@@ -3532,6 +3533,7 @@ static void X11DRV_DIB_SetImageBits_GetSubImage(
static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
{
int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
+ void *old_data = NULL;
XImage *bmpImage;
wine_tsx11_lock();
@@ -3556,6 +3558,22 @@ static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
bmpImage->depth,bmpImage->bits_per_pixel,
bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
+#ifdef HAVE_LIBXXSHM
+ if (descr->shm_mode == X11DRV_SHM_PIXMAP
+ && descr->xSrc == 0 && descr->ySrc == 0
+ && descr->xDest == 0 && descr->yDest == 0)
+ {
+ TRACE("Using the shared pixmap data.\n");
+
+ wine_tsx11_lock();
+ XSync( gdi_display, False );
+ wine_tsx11_unlock();
+
+ old_data = descr->image->data;
+ descr->image->data = descr->physBitmap->shminfo.shmaddr;
+ }
+#endif
+
/* Transfer the pixels */
__TRY
{
@@ -3635,7 +3653,13 @@ static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
if (lines)
{
#ifdef HAVE_LIBXXSHM
- if (descr->image && descr->useShm)
+ if (descr->shm_mode == X11DRV_SHM_PIXMAP
+ && descr->xSrc == 0 && descr->ySrc == 0
+ && descr->xDest == 0 && descr->yDest == 0)
+ {
+ XSync( gdi_display, False );
+ }
+ else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image)
{
XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
@@ -3644,10 +3668,15 @@ static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
}
else
#endif
+ {
XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
descr->width, descr->height );
+ }
}
+
+ if (old_data) descr->image->data = old_data;
+
if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
wine_tsx11_unlock();
return lines;
@@ -3661,6 +3690,7 @@ static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
{
int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
+ void *old_data = NULL;
XImage *bmpImage;
wine_tsx11_lock();
@@ -3682,8 +3712,20 @@ static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
/* We must not call XShmGetImage() with a bitmap which is bigger than the available area.
If we do, XShmGetImage() will fail (X exception), as it checks for this internally. */
- if((descr->image && descr->useShm) && (bmpImage->width <= (descr->width - descr->xSrc))
- && (bmpImage->height <= (descr->height - descr->ySrc)))
+ if (descr->shm_mode == X11DRV_SHM_PIXMAP && descr->image
+ && descr->xSrc == 0 && descr->ySrc == 0
+ && descr->xDest == 0 && descr->yDest == 0
+ && bmpImage->width <= (descr->width - descr->xSrc)
+ && bmpImage->height <= (descr->height - descr->ySrc))
+ {
+ XSync( gdi_display, False );
+ old_data = bmpImage->data;
+ bmpImage->data = descr->physBitmap->shminfo.shmaddr;
+ TRACE("Using shared pixmap data.\n");
+ }
+ else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image
+ && bmpImage->width <= (descr->width - descr->xSrc)
+ && bmpImage->height <= (descr->height - descr->ySrc))
{
int saveRed, saveGreen, saveBlue;
@@ -3786,6 +3828,7 @@ static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
break;
}
+ if (old_data) bmpImage->data = old_data;
if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
return lines;
}
@@ -3888,23 +3931,24 @@ INT CDECL X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDes
break;
}
- descr.physDev = physDev;
- descr.bits = bits;
- descr.image = NULL;
- descr.palentry = NULL;
- descr.lines = top_down ? -lines : lines;
- descr.infoWidth = width;
- descr.depth = physDev->depth;
- descr.drawable = physDev->drawable;
- descr.gc = physDev->gc;
- descr.xSrc = xSrc;
- descr.ySrc = ySrc;
- descr.xDest = physDev->dc_rect.left + pt.x;
- descr.yDest = physDev->dc_rect.top + pt.y;
- descr.width = cx;
- descr.height = cy;
- descr.useShm = FALSE;
- descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
+ descr.physDev = physDev;
+ descr.bits = bits;
+ descr.image = NULL;
+ descr.palentry = NULL;
+ descr.lines = top_down ? -lines : lines;
+ descr.infoWidth = width;
+ descr.depth = physDev->depth;
+ descr.drawable = physDev->drawable;
+ descr.gc = physDev->gc;
+ descr.xSrc = xSrc;
+ descr.ySrc = ySrc;
+ descr.xDest = physDev->dc_rect.left + pt.x;
+ descr.yDest = physDev->dc_rect.top + pt.y;
+ descr.width = cx;
+ descr.height = cy;
+ descr.shm_mode = X11DRV_SHM_NONE;
+ descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
+ descr.physBitmap = NULL;
result = X11DRV_DIB_SetImageBits( &descr );
@@ -3977,22 +4021,23 @@ INT CDECL X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT start
default: break;
}
- descr.bits = bits;
- descr.image = NULL;
- descr.palentry = NULL;
- descr.infoWidth = width;
- descr.lines = tmpheight >= 0 ? lines : -lines;
- descr.depth = physBitmap->pixmap_depth;
- descr.drawable = physBitmap->pixmap;
- descr.gc = get_bitmap_gc(physBitmap->pixmap_depth);
- descr.xSrc = 0;
- descr.ySrc = 0;
- descr.xDest = 0;
- descr.yDest = height - startscan - lines;
- descr.width = ds.dsBm.bmWidth;
- descr.height = lines;
- descr.useShm = FALSE;
- descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
+ descr.bits = bits;
+ descr.image = NULL;
+ descr.palentry = NULL;
+ descr.infoWidth = width;
+ descr.lines = tmpheight >= 0 ? lines : -lines;
+ descr.depth = physBitmap->pixmap_depth;
+ descr.drawable = physBitmap->pixmap;
+ descr.gc = get_bitmap_gc(physBitmap->pixmap_depth);
+ descr.xSrc = 0;
+ descr.ySrc = 0;
+ descr.xDest = 0;
+ descr.yDest = height - startscan - lines;
+ descr.width = ds.dsBm.bmWidth;
+ descr.height = lines;
+ descr.shm_mode = X11DRV_SHM_NONE;
+ descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
+ descr.physBitmap = NULL;
X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod );
result = X11DRV_DIB_SetImageBits( &descr );
@@ -4130,21 +4175,22 @@ INT CDECL X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT start
break;
}
- descr.physDev = physDev;
- descr.palentry = palette;
- descr.bits = bits;
- descr.image = physBitmap->image;
- descr.infoWidth = width;
- descr.lines = lines;
- descr.depth = physBitmap->pixmap_depth;
- descr.drawable = physBitmap->pixmap;
- descr.gc = get_bitmap_gc(physBitmap->pixmap_depth);
- descr.width = dib.dsBm.bmWidth;
- descr.height = dib.dsBm.bmHeight;
- descr.xDest = 0;
- descr.yDest = 0;
- descr.xSrc = 0;
- descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
+ descr.physDev = physDev;
+ descr.palentry = palette;
+ descr.bits = bits;
+ descr.image = physBitmap->image;
+ descr.infoWidth = width;
+ descr.lines = lines;
+ descr.depth = physBitmap->pixmap_depth;
+ descr.drawable = physBitmap->pixmap;
+ descr.gc = get_bitmap_gc(physBitmap->pixmap_depth);
+ descr.width = dib.dsBm.bmWidth;
+ descr.height = dib.dsBm.bmHeight;
+ descr.xDest = 0;
+ descr.yDest = 0;
+ descr.xSrc = 0;
+ descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
+ descr.physBitmap = physBitmap;
if (descr.lines > 0)
{
@@ -4154,11 +4200,7 @@ INT CDECL X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT start
{
descr.ySrc = startscan;
}
-#ifdef HAVE_LIBXXSHM
- descr.useShm = (obj_size == sizeof(DIBSECTION)) && (physBitmap->shminfo.shmid != -1);
-#else
- descr.useShm = FALSE;
-#endif
+ descr.shm_mode = physBitmap->shm_mode;
descr.dibpitch = (obj_size == sizeof(DIBSECTION)) ? dib.dsBm.bmWidthBytes
: (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
@@ -4205,17 +4247,18 @@ static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
- descr.physDev = NULL;
- descr.palentry = NULL;
- descr.infoWidth = dibSection.dsBmih.biWidth;
- descr.infoBpp = dibSection.dsBmih.biBitCount;
- descr.lines = dibSection.dsBmih.biHeight;
- descr.image = physBitmap->image;
- descr.colorMap = colorMap;
- descr.nColorMap = nColorMap;
- descr.bits = dibSection.dsBm.bmBits;
- descr.depth = physBitmap->pixmap_depth;
+ descr.physDev = NULL;
+ descr.palentry = NULL;
+ descr.infoWidth = dibSection.dsBmih.biWidth;
+ descr.infoBpp = dibSection.dsBmih.biBitCount;
+ descr.lines = dibSection.dsBmih.biHeight;
+ descr.image = physBitmap->image;
+ descr.colorMap = colorMap;
+ descr.nColorMap = nColorMap;
+ descr.bits = dibSection.dsBm.bmBits;
+ descr.depth = physBitmap->pixmap_depth;
descr.compression = dibSection.dsBmih.biCompression;
+ descr.physBitmap = physBitmap;
if(descr.infoBpp == 1)
descr.colorMap = (void*)identity;
@@ -4253,10 +4296,12 @@ static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
descr.height = height;
descr.sizeImage = 0;
+ descr.shm_mode = physBitmap->shm_mode;
#ifdef HAVE_LIBXXSHM
- descr.useShm = (physBitmap->shminfo.shmid != -1);
-#else
- descr.useShm = FALSE;
+ if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP && physBitmap->pixmap != dest)
+ {
+ descr.shm_mode = X11DRV_SHM_IMAGE;
+ }
#endif
descr.dibpitch = dibSection.dsBm.bmWidthBytes;
@@ -4645,7 +4690,7 @@ static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
IPC_CREAT|0700);
if( shminfo->shmid != -1 )
{
- shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
+ shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 );
if( shminfo->shmaddr != (char*)-1 )
{
BOOL ok;
@@ -4683,6 +4728,10 @@ HBITMAP CDECL X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
{
X_PHYSBITMAP *physBitmap;
DIBSECTION dib;
+#ifdef HAVE_LIBXXSHM
+ int major, minor;
+ Bool pixmaps;
+#endif
if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
physBitmap->status = DIB_Status_None;
@@ -4700,16 +4749,49 @@ HBITMAP CDECL X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
/* create pixmap and X image */
wine_tsx11_lock();
physBitmap->pixmap_depth = (dib.dsBm.bmBitsPixel == 1) ? 1 : screen_depth;
- physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
- dib.dsBm.bmHeight, physBitmap->pixmap_depth );
#ifdef HAVE_LIBXXSHM
physBitmap->shminfo.shmid = -1;
- if (!XShmQueryExtension(gdi_display) ||
- !(physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
- physBitmap->pixmap_depth, &physBitmap->shminfo )) )
+
+ if (XShmQueryVersion( gdi_display, &major, &minor, &pixmaps )
+ && (physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
+ physBitmap->pixmap_depth, &physBitmap->shminfo )))
+ {
+ if (pixmaps)
+ {
+ physBitmap->shm_mode = X11DRV_SHM_PIXMAP;
+ physBitmap->image->data = HeapAlloc( GetProcessHeap(), 0,
+ dib.dsBm.bmHeight * physBitmap->image->bytes_per_line );
+ }
+ else
+ {
+ physBitmap->shm_mode = X11DRV_SHM_IMAGE;
+ physBitmap->image->data = physBitmap->shminfo.shmaddr;
+ }
+ }
+ else
#endif
+ {
+ physBitmap->shm_mode = X11DRV_SHM_NONE;
physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
physBitmap->pixmap_depth );
+ }
+
+#ifdef HAVE_LIBXXSHM
+ if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP)
+ {
+ TRACE("Creating shared pixmap for bmp %p.\n", physBitmap->hbitmap);
+ physBitmap->pixmap = XShmCreatePixmap( gdi_display, root_window,
+ physBitmap->shminfo.shmaddr, &physBitmap->shminfo,
+ dib.dsBm.bmWidth, dib.dsBm.bmHeight,
+ physBitmap->pixmap_depth );
+ }
+ else
+#endif
+ {
+ physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
+ dib.dsBm.bmHeight, physBitmap->pixmap_depth );
+ }
+
wine_tsx11_unlock();
if (!physBitmap->pixmap || !physBitmap->image) return 0;
@@ -4760,9 +4842,11 @@ void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
if (physBitmap->shminfo.shmid != -1)
{
XShmDetach( gdi_display, &(physBitmap->shminfo) );
- XDestroyImage( physBitmap->image );
+ if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP) X11DRV_DIB_DestroyXImage( physBitmap->image );
+ else XDestroyImage( physBitmap->image );
shmdt( physBitmap->shminfo.shmaddr );
physBitmap->shminfo.shmid = -1;
+ physBitmap->shm_mode = X11DRV_SHM_NONE;
}
else
#endif
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 1a7a634..26671eb 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -92,6 +92,13 @@ typedef struct
Pixmap pixmap;
} X_PHYSBRUSH;
+enum x11drv_shm_mode
+{
+ X11DRV_SHM_NONE = 0,
+ X11DRV_SHM_PIXMAP,
+ X11DRV_SHM_IMAGE,
+};
+
/* X physical bitmap */
typedef struct
{
@@ -105,6 +112,7 @@ typedef struct
int *colorMap; /* color map info */
int nColorMap;
CRITICAL_SECTION lock; /* GDI access lock */
+ enum x11drv_shm_mode shm_mode;
#ifdef HAVE_LIBXXSHM
XShmSegmentInfo shminfo; /* shared memory segment info */
#endif
--
1.6.0.6
More information about the wine-patches
mailing list