winex11: Allow the visible region to be zero when not clipping.

This commit is contained in:
Alexandre Julliard 2011-12-06 14:00:14 +01:00
parent 649e33de58
commit 8d6354c5b2
5 changed files with 104 additions and 70 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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 );