winex11: Add a helper function to create the source pixmap from an image.

This commit is contained in:
Alexandre Julliard 2011-09-20 11:21:00 +02:00
parent af6fd252ef
commit aa4655e899
1 changed files with 74 additions and 50 deletions

View File

@ -2388,6 +2388,56 @@ static void get_colors( struct xrender_physdev *physdev_src, struct xrender_phys
get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->backgroundPixel, bg );
}
/* create a pixmap and render picture for an image */
static DWORD create_image_pixmap( BITMAPINFO *info, const struct gdi_image_bits *bits,
struct bitblt_coords *src, enum wxr_format format,
Pixmap *pixmap, Picture *pict, BOOL *use_repeat )
{
DWORD ret;
int width = src->visrect.right - src->visrect.left;
int height = src->visrect.bottom - src->visrect.top;
int depth = pict_formats[format]->depth;
struct gdi_image_bits dst_bits;
XRenderPictureAttributes pa;
XImage *image;
wine_tsx11_lock();
image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
info->bmiHeader.biWidth, height, 32, 0 );
wine_tsx11_unlock();
if (!image) return ERROR_OUTOFMEMORY;
ret = copy_image_bits( info, (format == WXR_FORMAT_R8G8B8), image, bits, &dst_bits, src, NULL, ~0u );
if (ret) return ret;
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 );
*use_repeat = (width == 1 && height == 1);
pa.repeat = *use_repeat ? RepeatNormal : RepeatNone;
wine_tsx11_lock();
*pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
XPutImage( gdi_display, *pixmap, get_bitmap_gc( depth ), image,
src->visrect.left, 0, 0, 0, width, height );
*pict = pXRenderCreatePicture( gdi_display, *pixmap, pict_formats[format], CPRepeat, &pa );
wine_tsx11_unlock();
/* make coordinates relative to the pixmap */
src->x -= src->visrect.left;
src->y -= src->visrect.top;
OffsetRect( &src->visrect, -src->visrect.left, -src->visrect.top );
image->data = NULL;
wine_tsx11_lock();
XDestroyImage( image );
wine_tsx11_unlock();
if (dst_bits.free) dst_bits.free( &dst_bits );
return ret;
}
static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
Drawable drawable, HRGN clip, const struct bitblt_coords *src,
const struct bitblt_coords *dst )
@ -2488,21 +2538,18 @@ static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xr
HeapFree( GetProcessHeap(), 0, clip_data );
}
static void xrender_put_image( XImage *image, HRGN clip, XRenderPictFormat *src_format,
static void xrender_put_image( Pixmap src_pixmap, Picture src_pict, HRGN clip,
XRenderPictFormat *dst_format, struct xrender_physdev *physdev,
Drawable drawable, struct bitblt_coords *src, struct bitblt_coords *dst )
Drawable drawable, struct bitblt_coords *src,
struct bitblt_coords *dst, BOOL use_repeat )
{
int x_src, y_src, x_dst, y_dst;
Picture dst_pict, src_pict;
Picture dst_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 );
@ -2524,35 +2571,25 @@ static void xrender_put_image( XImage *image, HRGN clip, XRenderPictFormat *src_
if (clip) clip_data = add_xrender_clipping_region( physdev, clip );
}
if (image->width == 1 && image->height == 1)
if (!use_repeat)
{
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;
}
else xscale = yscale = 1; /* no scaling needed with a repeating source */
x_src = src->x;
y_src = src->y;
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 );
@ -2655,12 +2692,13 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA
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;
Pixmap src_pixmap;
Picture src_pict;
BOOL use_repeat;
if (!X11DRV_XRender_Installed) goto x11drv_fallback;
@ -2691,24 +2729,11 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA
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 );
ret = create_image_pixmap( info, bits, src, src_format, &src_pixmap, &src_pict, &use_repeat );
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 );
@ -2716,8 +2741,8 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA
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 );
xrender_put_image( src_pixmap, src_pict, rgn, pict_formats[dst_format],
NULL, bitmap->pixmap, src, dst, use_repeat );
X11DRV_DIB_Unlock( bitmap, TRUE );
DeleteObject( rgn );
@ -2746,8 +2771,8 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA
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 );
xrender_put_image( src_pixmap, src_pict, NULL, physdev->pict_format,
NULL, tmp_pixmap, src, &tmp, use_repeat );
execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
wine_tsx11_lock();
@ -2761,20 +2786,19 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA
{
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 );
xrender_put_image( src_pixmap, src_pict, rgn,
physdev->pict_format, physdev, 0, src, dst, use_repeat );
DeleteObject( rgn );
}
X11DRV_UnlockDIBSection( physdev->x11dev, !ret );
X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
}
image->data = NULL;
wine_tsx11_lock();
pXRenderFreePicture( gdi_display, src_pict );
XFreePixmap( gdi_display, src_pixmap );
wine_tsx11_unlock();
}
wine_tsx11_lock();
XDestroyImage( image );
wine_tsx11_unlock();
if (dst_bits.free) dst_bits.free( &dst_bits );
return ret;
update_format: