From dfc8f184841408f510086e1bab68bd53a89818d5 Mon Sep 17 00:00:00 2001
From: Roderick Colenbrander <thunderbird2k@gmail.com>
Date: Thu, 8 Oct 2009 17:24:46 +0200
Subject: [PATCH] Introduce get_xrender_picture for retrieving a Picture from a physDev and allocating a Picture when needed.

---
 dlls/winex11.drv/xrender.c |   67 ++++++++++++++++++++++++++++++-------------
 1 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c
index 8b2f0dd..25eac65 100644
--- a/dlls/winex11.drv/xrender.c
+++ b/dlls/winex11.drv/xrender.c
@@ -144,6 +144,7 @@ struct xrender_info
 {
     int                cache_index;
     Picture            pict;
+    Picture            pict_src;
 };
 
 
@@ -482,6 +483,45 @@ static WineXRenderFormat *get_xrender_format_from_color_shifts(int depth, ColorS
     return NULL;
 }
 
+static Picture get_xrender_picture(X11DRV_PDEVICE *physDev, BOOL is_source)
+{
+    struct xrender_info *info = get_xrender_info(physDev);
+    if(!info)
+    {
+        ERR("Unable to obtain xrender info!\n");
+        return 0;
+    }
+
+    if(!info->pict)
+    {
+        WineXRenderFormat *fmt;
+        XRenderPictureAttributes pa;
+        pa.subwindow_mode = IncludeInferiors;
+
+        fmt = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
+        if(!fmt)
+        {
+            ERR("No xrender format found for physDev=%p, expect issues!\n", physDev);
+            return 0;
+        }
+
+        wine_tsx11_lock();
+        /* When a clipping region is set on a picture it is used during all operations. When the picture is a source we don't want
+         * to use clipping. For this reason we have a picture dedicated to source operations to which we never set a clipping region.
+         */
+        info->pict = pXRenderCreatePicture(gdi_display, physDev->drawable, fmt->pict_format, CPSubwindowMode, &pa);
+        info->pict_src = pXRenderCreatePicture(gdi_display, physDev->drawable, fmt->pict_format, CPSubwindowMode, &pa);
+        wine_tsx11_unlock();
+
+        TRACE("Allocing pict=%lx pict_src=%lx dc=%p drawable=%08lx fmt=%#x\n", info->pict, info->pict_src, physDev->hdc, physDev->drawable, fmt->format);
+    }
+
+    if(is_source)
+        return info->pict_src;
+
+    return info->pict;
+}
+
 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
 {
   if(p1->hash != p2->hash) return TRUE;
@@ -890,10 +930,12 @@ void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
 
     if(physDev->xrender->pict)
     {
-        TRACE("freeing pict = %lx dc = %p\n", physDev->xrender->pict, physDev->hdc);
+        TRACE("freeing pict = %lx pict_src = %lx dc = %p\n", physDev->xrender->pict, physDev->xrender->pict_src, physDev->hdc);
         XFlush(gdi_display);
         pXRenderFreePicture(gdi_display, physDev->xrender->pict);
+        pXRenderFreePicture(gdi_display, physDev->xrender->pict_src);
         physDev->xrender->pict = 0;
+        physDev->xrender->pict_src = 0;
     }
     wine_tsx11_unlock();
 
@@ -1434,7 +1476,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
     gsCacheEntry *entry;
     gsCacheEntryFormat *formatEntry;
     BOOL retv = FALSE;
-    HDC hdc = physDev->hdc;
     int textPixel, backgroundPixel;
     HRGN saved_region = 0;
     BOOL disable_antialias = FALSE;
@@ -1516,27 +1557,12 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
     }
 
     if(X11DRV_XRender_Installed) {
-        if(!physDev->xrender->pict) {
-	    XRenderPictureAttributes pa;
-	    pa.subwindow_mode = IncludeInferiors;
-
-	    wine_tsx11_lock();
-	    physDev->xrender->pict = pXRenderCreatePicture(gdi_display,
-							   physDev->drawable, dst_format->pict_format,
-							   CPSubwindowMode, &pa);
-	    wine_tsx11_unlock();
-
-	    TRACE("allocing pict = %lx dc = %p drawable = %08lx\n",
-                  physDev->xrender->pict, hdc, physDev->drawable);
-	} else {
-	    TRACE("using existing pict = %lx dc = %p drawable = %08lx\n",
-                  physDev->xrender->pict, hdc, physDev->drawable);
-	}
+        Picture pict = get_xrender_picture(physDev, FALSE);
 
 	if ((data = X11DRV_GetRegionData( physDev->region, 0 )))
 	{
 	    wine_tsx11_lock();
-	    pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
+	    pXRenderSetPictureClipRectangles( gdi_display, pict,
 					      physDev->dc_rect.left, physDev->dc_rect.top,
 					      (XRectangle *)data->Buffer, data->rdh.nCount );
 	    wine_tsx11_unlock();
@@ -1578,6 +1604,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
         INT offset = 0;
         POINT desired, current;
         int render_op = PictOpOver;
+        Picture pict = get_xrender_picture(physDev, FALSE);
 
         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
            So we pass zeros to the function and move to our starting position using the first
@@ -1620,7 +1647,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
         wine_tsx11_lock();
         pXRenderCompositeText16(gdi_display, render_op,
                                 tile_pict,
-                                physDev->xrender->pict,
+                                pict,
                                 formatEntry->font_format->pict_format,
                                 0, 0, 0, 0, elts, count);
         wine_tsx11_unlock();
-- 
1.6.0.4

