winex11: Implement a PutImage entry point in the XRender driver.
This commit is contained in:
parent
3e5f87aee6
commit
d905ba5a33
|
@ -1540,9 +1540,9 @@ static inline BOOL is_r8g8b8( int depth, const ColorShifts *color_shifts )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the image bits, fixing up alignment and byte swapping as necessary */
|
/* copy the image bits, fixing up alignment and byte swapping as necessary */
|
||||||
static DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
|
DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
|
||||||
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
|
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
|
||||||
struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
|
struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
|
||||||
{
|
{
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
static const int client_byte_order = MSBFirst;
|
static const int client_byte_order = MSBFirst;
|
||||||
|
|
|
@ -277,6 +277,9 @@ extern X_PHYSBITMAP *X11DRV_init_phys_bitmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL X11DRV_create_phys_bitmap( HBITMAP hbitmap, const BITMAP *bitmap, int depth,
|
extern BOOL X11DRV_create_phys_bitmap( HBITMAP hbitmap, const BITMAP *bitmap, int depth,
|
||||||
int true_color, const ColorShifts *shifts ) DECLSPEC_HIDDEN;
|
int true_color, const ColorShifts *shifts ) DECLSPEC_HIDDEN;
|
||||||
extern Pixmap X11DRV_get_pixmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN;
|
extern Pixmap X11DRV_get_pixmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN;
|
||||||
|
extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
|
||||||
|
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
|
||||||
|
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 *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN;
|
||||||
extern void update_x11_clipping( X11DRV_PDEVICE *physDev, const RGNDATA *data ) DECLSPEC_HIDDEN;
|
extern void update_x11_clipping( X11DRV_PDEVICE *physDev, const RGNDATA *data ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright 2001, 2002 Huw D M Davies for CodeWeavers
|
* Copyright 2001, 2002 Huw D M Davies for CodeWeavers
|
||||||
* Copyright 2009 Roderick Colenbrander
|
* Copyright 2009 Roderick Colenbrander
|
||||||
|
* Copyright 2011 Alexandre Julliard
|
||||||
*
|
*
|
||||||
* Some parts also:
|
* Some parts also:
|
||||||
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
|
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||||
|
@ -489,6 +490,44 @@ static enum wxr_format get_xrender_format_from_color_shifts(int depth, ColorShif
|
||||||
return WXR_INVALID_FORMAT;
|
return WXR_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum wxr_format get_xrender_format_from_bitmapinfo( const BITMAPINFO *info, BOOL use_alpha )
|
||||||
|
{
|
||||||
|
if (info->bmiHeader.biPlanes != 1) return WXR_INVALID_FORMAT;
|
||||||
|
|
||||||
|
switch (info->bmiHeader.biBitCount)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return WXR_FORMAT_MONO;
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
if (info->bmiHeader.biCompression != BI_RGB) break;
|
||||||
|
return WXR_FORMAT_R8G8B8;
|
||||||
|
case 16:
|
||||||
|
case 32:
|
||||||
|
if (info->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
|
{
|
||||||
|
DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < WXR_NB_FORMATS; i++)
|
||||||
|
{
|
||||||
|
if (info->bmiHeader.biBitCount == wxr_formats_template[i].depth &&
|
||||||
|
colors[0] == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
|
||||||
|
colors[1] == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
|
||||||
|
colors[2] == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (info->bmiHeader.biCompression != BI_RGB) break;
|
||||||
|
if (info->bmiHeader.biBitCount == 16) return WXR_FORMAT_X1R5G5B5;
|
||||||
|
return use_alpha ? WXR_FORMAT_A8R8G8B8 : WXR_FORMAT_X8R8G8B8;
|
||||||
|
}
|
||||||
|
return WXR_INVALID_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
|
/* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
|
||||||
static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
|
static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
|
||||||
{
|
{
|
||||||
|
@ -1117,6 +1156,35 @@ static BOOL create_xrender_dc( PHYSDEV *pdev )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* store the color mask data in the bitmap info structure */
|
||||||
|
static void set_color_info( XRenderPictFormat *format, BITMAPINFO *info )
|
||||||
|
{
|
||||||
|
DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
|
||||||
|
|
||||||
|
info->bmiHeader.biPlanes = 1;
|
||||||
|
info->bmiHeader.biBitCount = pixmap_formats[format->depth]->bits_per_pixel;
|
||||||
|
info->bmiHeader.biCompression = BI_RGB;
|
||||||
|
info->bmiHeader.biClrUsed = 0;
|
||||||
|
|
||||||
|
switch (info->bmiHeader.biBitCount)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
colors[0] = format->direct.redMask << format->direct.red;
|
||||||
|
colors[1] = format->direct.greenMask << format->direct.green;
|
||||||
|
colors[2] = format->direct.blueMask << format->direct.blue;
|
||||||
|
info->bmiHeader.biCompression = BI_BITFIELDS;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
colors[0] = format->direct.redMask << format->direct.red;
|
||||||
|
colors[1] = format->direct.greenMask << format->direct.green;
|
||||||
|
colors[2] = format->direct.blueMask << format->direct.blue;
|
||||||
|
if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
|
||||||
|
info->bmiHeader.biCompression = BI_BITFIELDS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* xrenderdrv_CreateDC
|
* xrenderdrv_CreateDC
|
||||||
*/
|
*/
|
||||||
|
@ -1247,18 +1315,6 @@ static DWORD xrenderdrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info
|
||||||
return dev->funcs->pGetImage( dev, hbitmap, info, bits, src );
|
return dev->funcs->pGetImage( dev, hbitmap, info, bits, src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* xrenderdrv_PutImage
|
|
||||||
*/
|
|
||||||
static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
|
|
||||||
const struct gdi_image_bits *bits, struct bitblt_coords *src,
|
|
||||||
struct bitblt_coords *dst, DWORD rop )
|
|
||||||
{
|
|
||||||
if (hbitmap) return X11DRV_PutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
|
|
||||||
dev = GET_NEXT_PHYSDEV( dev, pPutImage );
|
|
||||||
return dev->funcs->pPutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* xrenderdrv_SetDeviceClipping
|
* xrenderdrv_SetDeviceClipping
|
||||||
*/
|
*/
|
||||||
|
@ -2432,6 +2488,77 @@ static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xr
|
||||||
HeapFree( GetProcessHeap(), 0, clip_data );
|
HeapFree( GetProcessHeap(), 0, clip_data );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xrender_put_image( XImage *image, HRGN clip, XRenderPictFormat *src_format,
|
||||||
|
XRenderPictFormat *dst_format, struct xrender_physdev *physdev,
|
||||||
|
Drawable drawable, struct bitblt_coords *src, struct bitblt_coords *dst )
|
||||||
|
{
|
||||||
|
int x_src, y_src, x_dst, y_dst;
|
||||||
|
Picture dst_pict, src_pict;
|
||||||
|
XRenderPictureAttributes pa;
|
||||||
|
Pixmap src_pixmap;
|
||||||
|
double xscale, yscale;
|
||||||
|
RGNDATA *clip_data = NULL;
|
||||||
|
|
||||||
|
/* make source relative to tmp pixmap origin */
|
||||||
|
x_src = src->x - src->visrect.left;
|
||||||
|
y_src = src->y - src->visrect.top;
|
||||||
|
|
||||||
|
if (drawable) /* using an intermediate pixmap */
|
||||||
|
{
|
||||||
|
if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
|
||||||
|
x_dst = dst->x;
|
||||||
|
y_dst = dst->y;
|
||||||
|
pa.repeat = RepeatNone;
|
||||||
|
wine_tsx11_lock();
|
||||||
|
dst_pict = pXRenderCreatePicture( gdi_display, drawable, dst_format, CPRepeat, &pa );
|
||||||
|
if (clip_data)
|
||||||
|
pXRenderSetPictureClipRectangles( gdi_display, dst_pict, 0, 0,
|
||||||
|
(XRectangle *)clip_data->Buffer, clip_data->rdh.nCount );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x_dst = physdev->x11dev->dc_rect.left + dst->x;
|
||||||
|
y_dst = physdev->x11dev->dc_rect.top + dst->y;
|
||||||
|
dst_pict = get_xrender_picture( physdev );
|
||||||
|
if (clip) clip_data = add_xrender_clipping_region( physdev, clip );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image->width == 1 && image->height == 1)
|
||||||
|
{
|
||||||
|
pa.repeat = RepeatNormal;
|
||||||
|
xscale = yscale = 1; /* no scaling needed with a repeating source */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pa.repeat = RepeatNone;
|
||||||
|
xscale = src->width / (double)dst->width;
|
||||||
|
yscale = src->height / (double)dst->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->width < 0) x_src += src->width + 1;
|
||||||
|
if (src->height < 0) y_src += src->height + 1;
|
||||||
|
if (dst->width < 0) x_dst += dst->width + 1;
|
||||||
|
if (dst->height < 0) y_dst += dst->height + 1;
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
src_pixmap = XCreatePixmap( gdi_display, root_window, image->width, image->height, src_format->depth );
|
||||||
|
XPutImage( gdi_display, src_pixmap, get_bitmap_gc( src_format->depth ),
|
||||||
|
image, src->visrect.left, 0, 0, 0, image->width, image->height );
|
||||||
|
src_pict = pXRenderCreatePicture( gdi_display, src_pixmap, src_format, CPRepeat, &pa );
|
||||||
|
|
||||||
|
xrender_blit( PictOpSrc, src_pict, 0, dst_pict, x_src, y_src, x_dst, y_dst,
|
||||||
|
xscale, yscale, abs( dst->width ), abs( dst->height ));
|
||||||
|
|
||||||
|
if (drawable) pXRenderFreePicture( gdi_display, dst_pict );
|
||||||
|
pXRenderFreePicture( gdi_display, src_pict );
|
||||||
|
XFreePixmap( gdi_display, src_pixmap );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
|
||||||
|
if (!drawable) update_xrender_clipping( physdev, clip_data );
|
||||||
|
HeapFree( GetProcessHeap(), 0, clip_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* xrenderdrv_StretchBlt
|
* xrenderdrv_StretchBlt
|
||||||
|
@ -2518,6 +2645,150 @@ x11drv_fallback:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* xrenderdrv_PutImage
|
||||||
|
*/
|
||||||
|
static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
|
||||||
|
const struct gdi_image_bits *bits, struct bitblt_coords *src,
|
||||||
|
struct bitblt_coords *dst, DWORD rop )
|
||||||
|
{
|
||||||
|
struct xrender_physdev *physdev;
|
||||||
|
X_PHYSBITMAP *bitmap;
|
||||||
|
DWORD ret;
|
||||||
|
XImage *image;
|
||||||
|
Pixmap tmp_pixmap;
|
||||||
|
GC gc;
|
||||||
|
struct gdi_image_bits dst_bits;
|
||||||
|
enum wxr_format src_format, dst_format;
|
||||||
|
XRenderPictFormat *pict_format;
|
||||||
|
|
||||||
|
if (!X11DRV_XRender_Installed) goto x11drv_fallback;
|
||||||
|
|
||||||
|
if (hbitmap)
|
||||||
|
{
|
||||||
|
if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
|
||||||
|
physdev = NULL;
|
||||||
|
dst_format = get_xrender_format_from_color_shifts( bitmap->pixmap_depth,
|
||||||
|
&bitmap->pixmap_color_shifts );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
physdev = get_xrender_dev( dev );
|
||||||
|
bitmap = NULL;
|
||||||
|
dst_format = physdev->format;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_format = get_xrender_format_from_bitmapinfo( info, TRUE );
|
||||||
|
if (!(pict_format = pict_formats[src_format])) goto update_format;
|
||||||
|
|
||||||
|
/* make sure we can create an image with the same bpp */
|
||||||
|
if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
|
||||||
|
goto update_format;
|
||||||
|
|
||||||
|
/* mono <-> color conversions not supported */
|
||||||
|
if ((src_format != dst_format) && (src_format == WXR_FORMAT_MONO || dst_format == WXR_FORMAT_MONO))
|
||||||
|
goto x11drv_fallback;
|
||||||
|
|
||||||
|
if (!bits) return ERROR_SUCCESS; /* just querying the format */
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
image = XCreateImage( gdi_display, visual, pict_format->depth, ZPixmap, 0, NULL,
|
||||||
|
info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
if (!image) return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
ret = copy_image_bits( info, (src_format == WXR_FORMAT_R8G8B8),
|
||||||
|
image, bits, &dst_bits, src, NULL, ~0u );
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
struct bitblt_coords tmp;
|
||||||
|
|
||||||
|
image->data = dst_bits.ptr;
|
||||||
|
/* hack: make sure the bits are readable if we are reading from a DIB section */
|
||||||
|
/* to be removed once we get rid of DIB access protections */
|
||||||
|
if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, image->height * image->bytes_per_line );
|
||||||
|
|
||||||
|
if (bitmap)
|
||||||
|
{
|
||||||
|
HRGN rgn = CreateRectRgnIndirect( &dst->visrect );
|
||||||
|
if (clip) CombineRgn( rgn, rgn, clip, RGN_AND );
|
||||||
|
|
||||||
|
X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
|
||||||
|
|
||||||
|
xrender_put_image( image, rgn, pict_formats[src_format], pict_formats[dst_format],
|
||||||
|
NULL, bitmap->pixmap, src, dst );
|
||||||
|
|
||||||
|
X11DRV_DIB_Unlock( bitmap, TRUE );
|
||||||
|
DeleteObject( rgn );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
|
||||||
|
|
||||||
|
if (rop != SRCCOPY)
|
||||||
|
{
|
||||||
|
RGNDATA *clip_data = NULL;
|
||||||
|
|
||||||
|
/* make coordinates relative to tmp pixmap */
|
||||||
|
tmp = *dst;
|
||||||
|
tmp.x -= tmp.visrect.left;
|
||||||
|
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 );
|
||||||
|
XSetGraphicsExposures( gdi_display, gc, False );
|
||||||
|
tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
|
||||||
|
tmp.visrect.bottom - tmp.visrect.top, physdev->x11dev->depth );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
|
||||||
|
xrender_put_image( image, NULL, pict_format, physdev->pict_format,
|
||||||
|
NULL, tmp_pixmap, src, &tmp );
|
||||||
|
execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
XFreePixmap( gdi_display, tmp_pixmap );
|
||||||
|
XFreeGC( gdi_display, gc );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
|
||||||
|
restore_clipping_region( physdev->x11dev, clip_data );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HRGN rgn = CreateRectRgnIndirect( &dst->visrect );
|
||||||
|
if (clip) CombineRgn( rgn, rgn, clip, RGN_AND );
|
||||||
|
xrender_put_image( image, rgn, pict_format, physdev->pict_format, physdev, 0, src, dst );
|
||||||
|
DeleteObject( rgn );
|
||||||
|
}
|
||||||
|
|
||||||
|
X11DRV_UnlockDIBSection( physdev->x11dev, !ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
image->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
XDestroyImage( image );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
if (dst_bits.free) dst_bits.free( &dst_bits );
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
update_format:
|
||||||
|
if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
|
||||||
|
set_color_info( pict_formats[dst_format], info );
|
||||||
|
return ERROR_BAD_FORMAT;
|
||||||
|
|
||||||
|
x11drv_fallback:
|
||||||
|
if (hbitmap) return X11DRV_PutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
|
||||||
|
dev = GET_NEXT_PHYSDEV( dev, pPutImage );
|
||||||
|
return dev->funcs->pPutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* xrenderdrv_AlphaBlend
|
* xrenderdrv_AlphaBlend
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue