diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 9830327dce..d75e90214e 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1280,9 +1280,8 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info } else { - RGNDATA *saved_region = NULL; + BOOL restore_region = add_extra_clipping_region( physdev, clip ); - if (clip) saved_region = add_extra_clipping_region( physdev, clip ); X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod ); /* optimization for single-op ROPs */ @@ -1317,7 +1316,7 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info } X11DRV_UnlockDIBSection( physdev, !ret ); - restore_clipping_region( physdev, saved_region ); + if (restore_region) restore_clipping_region( physdev ); } image->data = NULL; } diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c index 356f7d7eb8..0f723893dc 100644 --- a/dlls/winex11.drv/graphics.c +++ b/dlls/winex11.drv/graphics.c @@ -188,12 +188,24 @@ RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) /*********************************************************************** * update_x11_clipping */ -static void update_x11_clipping( X11DRV_PDEVICE *physDev, const RGNDATA *data ) +static void update_x11_clipping( X11DRV_PDEVICE *physDev, HRGN rgn ) { - wine_tsx11_lock(); - XSetClipRectangles( gdi_display, physDev->gc, physDev->dc_rect.left, physDev->dc_rect.top, - (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded ); - wine_tsx11_unlock(); + RGNDATA *data; + + if (!rgn) + { + wine_tsx11_lock(); + XSetClipMask( gdi_display, physDev->gc, None ); + wine_tsx11_unlock(); + } + else if ((data = X11DRV_GetRegionData( rgn, 0 ))) + { + wine_tsx11_lock(); + XSetClipRectangles( gdi_display, physDev->gc, physDev->dc_rect.left, physDev->dc_rect.top, + (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded ); + wine_tsx11_unlock(); + HeapFree( GetProcessHeap(), 0, data ); + } } @@ -201,38 +213,31 @@ static void update_x11_clipping( X11DRV_PDEVICE *physDev, const RGNDATA *data ) * add_extra_clipping_region * * Temporarily add a region to the current clipping region. - * The returned region must be restored with restore_clipping_region. + * The region must be restored with restore_clipping_region. */ -RGNDATA *add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) +BOOL add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) { - RGNDATA *ret, *data; HRGN clip; - if (!(ret = X11DRV_GetRegionData( dev->region, 0 ))) return NULL; - if (!(clip = CreateRectRgn( 0, 0, 0, 0 ))) + if (!rgn) return FALSE; + if (dev->region) { - HeapFree( GetProcessHeap(), 0, ret ); - return NULL; + if (!(clip = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE; + CombineRgn( clip, dev->region, rgn, RGN_AND ); + update_x11_clipping( dev, clip ); + DeleteObject( clip ); } - CombineRgn( clip, dev->region, rgn, RGN_AND ); - if ((data = X11DRV_GetRegionData( clip, 0 ))) - { - update_x11_clipping( dev, data ); - HeapFree( GetProcessHeap(), 0, data ); - } - DeleteObject( clip ); - return ret; + else update_x11_clipping( dev, rgn ); + return TRUE; } /*********************************************************************** * restore_clipping_region */ -void restore_clipping_region( X11DRV_PDEVICE *dev, RGNDATA *data ) +void restore_clipping_region( X11DRV_PDEVICE *dev ) { - if (!data) return; - update_x11_clipping( dev, data ); - HeapFree( GetProcessHeap(), 0, data ); + update_x11_clipping( dev, dev->region ); } @@ -241,13 +246,10 @@ void restore_clipping_region( X11DRV_PDEVICE *dev, RGNDATA *data ) */ void X11DRV_SetDeviceClipping( PHYSDEV dev, HRGN rgn ) { - RGNDATA *data; X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); physDev->region = rgn; - - if ((data = X11DRV_GetRegionData( physDev->region, 0 ))) update_x11_clipping( physDev, data ); - HeapFree( GetProcessHeap(), 0, data ); + update_x11_clipping( physDev, rgn ); } @@ -1455,8 +1457,24 @@ BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillTy pt.x = x; pt.y = y; LPtoDP( dev->hdc, &pt, 1 ); - if (!PtInRegion( physDev->region, pt.x, pt.y )) return FALSE; - GetRgnBox( physDev->region, &rect ); + + if (!physDev->region) + { + rect.left = 0; + rect.top = 0; + rect.right = physDev->dc_rect.right - physDev->dc_rect.left; + rect.bottom = physDev->dc_rect.bottom - physDev->dc_rect.top; + } + else + { + if (!PtInRegion( physDev->region, pt.x, pt.y )) return FALSE; + GetRgnBox( physDev->region, &rect ); + rect.left = max( rect.left, 0 ); + rect.top = max( rect.top, 0 ); + rect.right = min( rect.right, physDev->dc_rect.right - physDev->dc_rect.left ); + rect.bottom = min( rect.bottom, physDev->dc_rect.bottom - physDev->dc_rect.top ); + } + if (pt.x < rect.left || pt.x >= rect.right || pt.y < rect.top || pt.y >= rect.bottom) return FALSE; X11DRV_expect_error( gdi_display, ExtFloodFillXGetImageErrorHandler, NULL ); image = XGetImage( gdi_display, physDev->drawable, diff --git a/dlls/winex11.drv/text.c b/dlls/winex11.drv/text.c index 96cc00b8a8..b1bcf67ca9 100644 --- a/dlls/winex11.drv/text.c +++ b/dlls/winex11.drv/text.c @@ -41,7 +41,7 @@ BOOL X11DRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx ) { X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); - RGNDATA *saved_region = NULL; + BOOL restore_region = FALSE; unsigned int i; fontObject* pfo = XFONT_GetFontObject( physDev->font ); XFontStruct* font; @@ -88,7 +88,7 @@ BOOL X11DRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, if (flags & ETO_CLIPPED) { HRGN clip_region = CreateRectRgnIndirect( lprect ); - saved_region = add_extra_clipping_region( physDev, clip_region ); + restore_region = add_extra_clipping_region( physDev, clip_region ); DeleteObject( clip_region ); } @@ -182,7 +182,7 @@ BOOL X11DRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, END: HeapFree( GetProcessHeap(), 0, str2b ); if (dibUpdateFlag) X11DRV_UnlockDIBSection( physDev, TRUE ); - restore_clipping_region( physDev, saved_region ); + if (restore_region) restore_clipping_region( physDev ); return result; } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index f1f22bd2b1..7c12360faa 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -286,8 +286,8 @@ extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask ) DECLSPEC_HIDDEN; extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN; -extern RGNDATA *add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN; -extern void restore_clipping_region( X11DRV_PDEVICE *dev, RGNDATA *data ) DECLSPEC_HIDDEN; +extern BOOL add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN; +extern void restore_clipping_region( X11DRV_PDEVICE *dev ) DECLSPEC_HIDDEN; extern void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c index 5aafd2df54..d81130da24 100644 --- a/dlls/winex11.drv/xrender.c +++ b/dlls/winex11.drv/xrender.c @@ -188,6 +188,7 @@ static void *xrender_handle; #define MAKE_FUNCPTR(f) static typeof(f) * p##f; MAKE_FUNCPTR(XRenderAddGlyphs) +MAKE_FUNCPTR(XRenderChangePicture) MAKE_FUNCPTR(XRenderComposite) MAKE_FUNCPTR(XRenderCompositeText16) MAKE_FUNCPTR(XRenderCreateGlyphSet) @@ -372,6 +373,7 @@ const struct gdi_dc_funcs *X11DRV_XRender_Init(void) #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) return NULL #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0) LOAD_FUNCPTR(XRenderAddGlyphs); + LOAD_FUNCPTR(XRenderChangePicture); LOAD_FUNCPTR(XRenderComposite); LOAD_FUNCPTR(XRenderCompositeText16); LOAD_FUNCPTR(XRenderCreateGlyphSet); @@ -578,6 +580,30 @@ static BOOL use_source_repeat( struct xrender_physdev *dev ) dev->x11dev->drawable_rect.bottom - dev->x11dev->drawable_rect.top == 1); } +static void update_xrender_clipping( struct xrender_physdev *dev, HRGN rgn ) +{ + XRenderPictureAttributes pa; + RGNDATA *data; + + if (!rgn) + { + wine_tsx11_lock(); + pa.clip_mask = None; + pXRenderChangePicture( gdi_display, dev->pict, CPClipMask, &pa ); + wine_tsx11_unlock(); + } + else if ((data = X11DRV_GetRegionData( rgn, 0 ))) + { + wine_tsx11_lock(); + pXRenderSetPictureClipRectangles( gdi_display, dev->pict, + dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top, + (XRectangle *)data->Buffer, data->rdh.nCount ); + wine_tsx11_unlock(); + HeapFree( GetProcessHeap(), 0, data ); + } +} + + static Picture get_xrender_picture( struct xrender_physdev *dev, HRGN clip_rgn, const RECT *clip_rect ) { if (!dev->pict && dev->pict_format) @@ -591,38 +617,31 @@ static Picture get_xrender_picture( struct xrender_physdev *dev, HRGN clip_rgn, wine_tsx11_unlock(); TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n", dev->pict, dev->dev.hdc, dev->x11dev->drawable ); - dev->update_clip = TRUE; + dev->update_clip = (dev->x11dev->region != 0); } - if (dev->update_clip || clip_rect || clip_rgn) + if (clip_rect) { - RGNDATA *clip_data; - HRGN rgn = 0; - - if (clip_rect) - { - rgn = CreateRectRgnIndirect( clip_rect ); - if (clip_rgn) CombineRgn( rgn, rgn, clip_rgn, RGN_AND ); - CombineRgn( rgn, rgn, dev->x11dev->region, RGN_AND ); - } - else if (clip_rgn) - { - rgn = CreateRectRgn( 0, 0, 0, 0 ); - CombineRgn( rgn, clip_rgn, dev->x11dev->region, RGN_AND ); - } - - if ((clip_data = X11DRV_GetRegionData( rgn ? rgn : dev->x11dev->region, 0 ))) - { - wine_tsx11_lock(); - pXRenderSetPictureClipRectangles( gdi_display, dev->pict, - dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top, - (XRectangle *)clip_data->Buffer, clip_data->rdh.nCount ); - wine_tsx11_unlock(); - HeapFree( GetProcessHeap(), 0, clip_data ); - } - dev->update_clip = (rgn != 0); /* have to update again if we are using a custom region */ - if (rgn) DeleteObject( rgn ); + HRGN rgn = CreateRectRgnIndirect( clip_rect ); + if (clip_rgn) CombineRgn( rgn, rgn, clip_rgn, RGN_AND ); + if (dev->x11dev->region) CombineRgn( rgn, rgn, dev->x11dev->region, RGN_AND ); + update_xrender_clipping( dev, rgn ); + DeleteObject( rgn ); } + else if (clip_rgn) + { + if (dev->x11dev->region) + { + HRGN rgn = CreateRectRgn( 0, 0, 0, 0 ); + CombineRgn( rgn, clip_rgn, dev->x11dev->region, RGN_AND ); + update_xrender_clipping( dev, rgn ); + DeleteObject( rgn ); + } + else update_xrender_clipping( dev, clip_rgn ); + } + else if (dev->update_clip) update_xrender_clipping( dev, dev->x11dev->region ); + + dev->update_clip = (clip_rect || clip_rgn); /* have to update again if we are using a custom region */ return dev->pict; } @@ -2288,7 +2307,7 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA if (rop != SRCCOPY) { - RGNDATA *clip_data = NULL; + BOOL restore_region = add_extra_clipping_region( physdev->x11dev, clip ); /* make coordinates relative to tmp pixmap */ tmp = *dst; @@ -2296,8 +2315,6 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA tmp.y -= tmp.visrect.top; OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top ); - if (clip) clip_data = add_extra_clipping_region( physdev->x11dev, clip ); - wine_tsx11_lock(); gc = XCreateGC( gdi_display, physdev->x11dev->drawable, 0, NULL ); XSetSubwindowMode( gdi_display, gc, IncludeInferiors ); @@ -2315,7 +2332,7 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA XFreeGC( gdi_display, gc ); wine_tsx11_unlock(); - restore_clipping_region( physdev->x11dev, clip_data ); + if (restore_region) restore_clipping_region( physdev->x11dev ); } else xrender_put_image( src_pixmap, src_pict, mask_pict, clip, physdev->pict_format, physdev, 0, src, dst, use_repeat );