winex11: Disable sub-pixel antialiasing if Xrender isn't supported.
[wine] / dlls / winex11.drv / xrender.c
1 /*
2  * Functions to use the XRender extension
3  *
4  * Copyright 2001, 2002 Huw D M Davies for CodeWeavers
5  * Copyright 2009 Roderick Colenbrander
6  *
7  * Some parts also:
8  * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "x11drv.h"
35 #include "winternl.h"
36 #include "wine/library.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
39
40 int using_client_side_fonts = FALSE;
41
42 WINE_DEFAULT_DEBUG_CHANNEL(xrender);
43
44 #ifdef SONAME_LIBXRENDER
45
46 static BOOL X11DRV_XRender_Installed = FALSE;
47
48 #include <X11/Xlib.h>
49 #include <X11/extensions/Xrender.h>
50
51 #ifndef RepeatNone  /* added in 0.10 */
52 #define RepeatNone    0
53 #define RepeatNormal  1
54 #define RepeatPad     2
55 #define RepeatReflect 3
56 #endif
57
58 typedef enum wine_xrformat
59 {
60   WXR_FORMAT_MONO,
61   WXR_FORMAT_GRAY,
62   WXR_FORMAT_X1R5G5B5,
63   WXR_FORMAT_X1B5G5R5,
64   WXR_FORMAT_R5G6B5,
65   WXR_FORMAT_B5G6R5,
66   WXR_FORMAT_R8G8B8,
67   WXR_FORMAT_B8G8R8,
68   WXR_FORMAT_A8R8G8B8,
69   WXR_FORMAT_B8G8R8A8,
70   WXR_FORMAT_X8R8G8B8,
71   WXR_FORMAT_B8G8R8X8,
72   WXR_NB_FORMATS
73 } WXRFormat;
74
75 typedef struct wine_xrender_format_template
76 {
77     WXRFormat wxr_format;
78     unsigned int depth;
79     unsigned int alpha;
80     unsigned int alphaMask;
81     unsigned int red;
82     unsigned int redMask;
83     unsigned int green;
84     unsigned int greenMask;
85     unsigned int blue;
86     unsigned int blueMask;
87 } WineXRenderFormatTemplate;
88
89 static const WineXRenderFormatTemplate wxr_formats_template[WXR_NB_FORMATS] =
90 {
91     /* Format               depth   alpha   mask    red     mask    green   mask    blue    mask*/
92     {WXR_FORMAT_MONO,       1,      0,      0x01,   0,      0,      0,      0,      0,      0       },
93     {WXR_FORMAT_GRAY,       8,      0,      0xff,   0,      0,      0,      0,      0,      0       },
94     {WXR_FORMAT_X1R5G5B5,   16,     0,      0,      10,     0x1f,   5,      0x1f,   0,      0x1f    },
95     {WXR_FORMAT_X1B5G5R5,   16,     0,      0,      0,      0x1f,   5,      0x1f,   10,     0x1f    },
96     {WXR_FORMAT_R5G6B5,     16,     0,      0,      11,     0x1f,   5,      0x3f,   0,      0x1f    },
97     {WXR_FORMAT_B5G6R5,     16,     0,      0,      0,      0x1f,   5,      0x3f,   11,     0x1f    },
98     {WXR_FORMAT_R8G8B8,     24,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
99     {WXR_FORMAT_B8G8R8,     24,     0,      0,      0,      0xff,   8,      0xff,   16,     0xff    },
100     {WXR_FORMAT_A8R8G8B8,   32,     24,     0xff,   16,     0xff,   8,      0xff,   0,      0xff    },
101     {WXR_FORMAT_B8G8R8A8,   32,     0,      0xff,   8,      0xff,   16,     0xff,   24,     0xff    },
102     {WXR_FORMAT_X8R8G8B8,   32,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
103     {WXR_FORMAT_B8G8R8X8,   32,     0,      0,      8,      0xff,   16,     0xff,   24,     0xff    },
104 };
105
106 typedef struct wine_xrender_format
107 {
108     WXRFormat               format;
109     XRenderPictFormat       *pict_format;
110 } WineXRenderFormat;
111
112 static WineXRenderFormat wxr_formats[WXR_NB_FORMATS];
113 static int WineXRenderFormatsListSize = 0;
114 static WineXRenderFormat *default_format = NULL;
115
116 typedef struct
117 {
118     LOGFONTW lf;
119     XFORM    xform;
120     SIZE     devsize;  /* size in device coords */
121     DWORD    hash;
122 } LFANDSIZE;
123
124 #define INITIAL_REALIZED_BUF_SIZE 128
125
126 typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
127
128 typedef struct
129 {
130     GlyphSet glyphset;
131     const WineXRenderFormat *font_format;
132     int nrealized;
133     BOOL *realized;
134     void **bitmaps;
135     XGlyphInfo *gis;
136 } gsCacheEntryFormat;
137
138 typedef struct
139 {
140     LFANDSIZE lfsz;
141     AA_Type aa_default;
142     gsCacheEntryFormat * format[AA_MAXVALUE];
143     INT count;
144     INT next;
145 } gsCacheEntry;
146
147 struct xrender_info
148 {
149     int                cache_index;
150     Picture            pict;
151     Picture            pict_src;
152     const WineXRenderFormat *format;
153 };
154
155 static gsCacheEntry *glyphsetCache = NULL;
156 static DWORD glyphsetCacheSize = 0;
157 static INT lastfree = -1;
158 static INT mru = -1;
159
160 #define INIT_CACHE_SIZE 10
161
162 static int antialias = 1;
163
164 static void *xrender_handle;
165
166 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
167 MAKE_FUNCPTR(XRenderAddGlyphs)
168 MAKE_FUNCPTR(XRenderComposite)
169 MAKE_FUNCPTR(XRenderCompositeString8)
170 MAKE_FUNCPTR(XRenderCompositeString16)
171 MAKE_FUNCPTR(XRenderCompositeString32)
172 MAKE_FUNCPTR(XRenderCompositeText16)
173 MAKE_FUNCPTR(XRenderCreateGlyphSet)
174 MAKE_FUNCPTR(XRenderCreatePicture)
175 MAKE_FUNCPTR(XRenderFillRectangle)
176 MAKE_FUNCPTR(XRenderFindFormat)
177 MAKE_FUNCPTR(XRenderFindVisualFormat)
178 MAKE_FUNCPTR(XRenderFreeGlyphSet)
179 MAKE_FUNCPTR(XRenderFreePicture)
180 MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
181 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
182 MAKE_FUNCPTR(XRenderSetPictureTransform)
183 #endif
184 MAKE_FUNCPTR(XRenderQueryExtension)
185
186 #ifdef SONAME_LIBFONTCONFIG
187 #include <fontconfig/fontconfig.h>
188 MAKE_FUNCPTR(FcConfigSubstitute)
189 MAKE_FUNCPTR(FcDefaultSubstitute)
190 MAKE_FUNCPTR(FcFontMatch)
191 MAKE_FUNCPTR(FcInit)
192 MAKE_FUNCPTR(FcPatternCreate)
193 MAKE_FUNCPTR(FcPatternDestroy)
194 MAKE_FUNCPTR(FcPatternAddInteger)
195 MAKE_FUNCPTR(FcPatternAddString)
196 MAKE_FUNCPTR(FcPatternGetBool)
197 MAKE_FUNCPTR(FcPatternGetInteger)
198 MAKE_FUNCPTR(FcPatternGetString)
199 static void *fontconfig_handle;
200 static BOOL fontconfig_installed;
201 #endif
202
203 #undef MAKE_FUNCPTR
204
205 static CRITICAL_SECTION xrender_cs;
206 static CRITICAL_SECTION_DEBUG critsect_debug =
207 {
208     0, 0, &xrender_cs,
209     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
210       0, 0, { (DWORD_PTR)(__FILE__ ": xrender_cs") }
211 };
212 static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
213
214 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
215           ( ( (ULONG)_x4 << 24 ) |     \
216             ( (ULONG)_x3 << 16 ) |     \
217             ( (ULONG)_x2 <<  8 ) |     \
218               (ULONG)_x1         )
219
220 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
221
222 #define GASP_GRIDFIT 0x01
223 #define GASP_DOGRAY  0x02
224
225 #ifdef WORDS_BIGENDIAN
226 #define get_be_word(x) (x)
227 #define NATIVE_BYTE_ORDER MSBFirst
228 #else
229 #define get_be_word(x) RtlUshortByteSwap(x)
230 #define NATIVE_BYTE_ORDER LSBFirst
231 #endif
232
233 static WXRFormat get_format_without_alpha( WXRFormat format )
234 {
235     switch (format)
236     {
237     case WXR_FORMAT_A8R8G8B8: return WXR_FORMAT_X8R8G8B8;
238     case WXR_FORMAT_B8G8R8A8: return WXR_FORMAT_B8G8R8X8;
239     default: return format;
240     }
241 }
242
243 static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
244 {
245     templ->id = 0;
246     templ->type = PictTypeDirect;
247     templ->depth = fmt->depth;
248     templ->direct.alpha = fmt->alpha;
249     templ->direct.alphaMask = fmt->alphaMask;
250     templ->direct.red = fmt->red;
251     templ->direct.redMask = fmt->redMask;
252     templ->direct.green = fmt->green;
253     templ->direct.greenMask = fmt->greenMask;
254     templ->direct.blue = fmt->blue;
255     templ->direct.blueMask = fmt->blueMask;
256     templ->colormap = 0;
257
258     *mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
259
260     return TRUE;
261 }
262
263 static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
264 {
265     if(fmt->depth != screen_depth)
266         return FALSE;
267     if( (fmt->redMask << fmt->red) != visual->red_mask)
268         return FALSE;
269     if( (fmt->greenMask << fmt->green) != visual->green_mask)
270         return FALSE;
271     if( (fmt->blueMask << fmt->blue) != visual->blue_mask)
272         return FALSE;
273
274     /* We never select a default ARGB visual */
275     if(fmt->alphaMask)
276         return FALSE;
277
278     return TRUE;
279 }
280
281 static int load_xrender_formats(void)
282 {
283     unsigned int i;
284     for(i = 0; i < (sizeof(wxr_formats_template) / sizeof(wxr_formats_template[0])); i++)
285     {
286         XRenderPictFormat templ, *pict_format;
287
288         if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
289         {
290             wine_tsx11_lock();
291             pict_format = pXRenderFindVisualFormat(gdi_display, visual);
292             if(!pict_format)
293             {
294                 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
295                 if (visual->class == DirectColor)
296                 {
297                     XVisualInfo info;
298                     if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
299                                           screen_depth, TrueColor, &info ))
300                     {
301                         pict_format = pXRenderFindVisualFormat(gdi_display, info.visual);
302                         if (pict_format) visual = info.visual;
303                     }
304                 }
305             }
306             wine_tsx11_unlock();
307
308             if(pict_format)
309             {
310                 wxr_formats[WineXRenderFormatsListSize].format = wxr_formats_template[i].wxr_format;
311                 wxr_formats[WineXRenderFormatsListSize].pict_format = pict_format;
312                 default_format = &wxr_formats[WineXRenderFormatsListSize];
313                 WineXRenderFormatsListSize++;
314                 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_format->id, wxr_formats_template[i].wxr_format);
315             }
316         }
317         else
318         {
319             unsigned long mask = 0;
320             get_xrender_template(&wxr_formats_template[i], &templ, &mask);
321
322             wine_tsx11_lock();
323             pict_format = pXRenderFindFormat(gdi_display, mask, &templ, 0);
324             wine_tsx11_unlock();
325
326             if(pict_format)
327             {
328                 wxr_formats[WineXRenderFormatsListSize].format = wxr_formats_template[i].wxr_format;
329                 wxr_formats[WineXRenderFormatsListSize].pict_format = pict_format;
330                 WineXRenderFormatsListSize++;
331                 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_format->id, wxr_formats_template[i].wxr_format);
332             }
333         }
334     }
335     return WineXRenderFormatsListSize;
336 }
337
338 /***********************************************************************
339  *   X11DRV_XRender_Init
340  *
341  * Let's see if our XServer has the extension available
342  *
343  */
344 void X11DRV_XRender_Init(void)
345 {
346     int event_base, i;
347
348     if (client_side_with_render &&
349         wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
350         wine_dlopen(SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0) && 
351         (xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0)))
352     {
353
354 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
355 LOAD_FUNCPTR(XRenderAddGlyphs)
356 LOAD_FUNCPTR(XRenderComposite)
357 LOAD_FUNCPTR(XRenderCompositeString8)
358 LOAD_FUNCPTR(XRenderCompositeString16)
359 LOAD_FUNCPTR(XRenderCompositeString32)
360 LOAD_FUNCPTR(XRenderCompositeText16)
361 LOAD_FUNCPTR(XRenderCreateGlyphSet)
362 LOAD_FUNCPTR(XRenderCreatePicture)
363 LOAD_FUNCPTR(XRenderFillRectangle)
364 LOAD_FUNCPTR(XRenderFindFormat)
365 LOAD_FUNCPTR(XRenderFindVisualFormat)
366 LOAD_FUNCPTR(XRenderFreeGlyphSet)
367 LOAD_FUNCPTR(XRenderFreePicture)
368 LOAD_FUNCPTR(XRenderSetPictureClipRectangles)
369 LOAD_FUNCPTR(XRenderQueryExtension)
370 #undef LOAD_FUNCPTR
371 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
372 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0);
373 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform)
374 #undef LOAD_OPTIONAL_FUNCPTR
375 #endif
376
377         wine_tsx11_lock();
378         X11DRV_XRender_Installed = pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base);
379         wine_tsx11_unlock();
380         if(X11DRV_XRender_Installed) {
381             TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
382             if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
383             {
384                 wine_tsx11_unlock();
385                 WINE_MESSAGE(
386                     "Wine has detected that you probably have a buggy version\n"
387                     "of libXrender.so .  Because of this client side font rendering\n"
388                     "will be disabled.  Please upgrade this library.\n");
389                 X11DRV_XRender_Installed = FALSE;
390                 return;
391             }
392
393             if (!visual->red_mask || !visual->green_mask || !visual->blue_mask) {
394                 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
395                 X11DRV_XRender_Installed = FALSE;
396             }
397         }
398     }
399
400 #ifdef SONAME_LIBFONTCONFIG
401     if ((fontconfig_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0)))
402     {
403 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(fontconfig_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
404         LOAD_FUNCPTR(FcConfigSubstitute);
405         LOAD_FUNCPTR(FcDefaultSubstitute);
406         LOAD_FUNCPTR(FcFontMatch);
407         LOAD_FUNCPTR(FcInit);
408         LOAD_FUNCPTR(FcPatternCreate);
409         LOAD_FUNCPTR(FcPatternDestroy);
410         LOAD_FUNCPTR(FcPatternAddInteger);
411         LOAD_FUNCPTR(FcPatternAddString);
412         LOAD_FUNCPTR(FcPatternGetBool);
413         LOAD_FUNCPTR(FcPatternGetInteger);
414         LOAD_FUNCPTR(FcPatternGetString);
415 #undef LOAD_FUNCPTR
416         fontconfig_installed = pFcInit();
417     }
418     else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG "\n" );
419 #endif
420
421 sym_not_found:
422     if(X11DRV_XRender_Installed || client_side_with_core)
423     {
424         glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
425                                   sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
426
427         glyphsetCacheSize = INIT_CACHE_SIZE;
428         lastfree = 0;
429         for(i = 0; i < INIT_CACHE_SIZE; i++) {
430           glyphsetCache[i].next = i + 1;
431           glyphsetCache[i].count = -1;
432         }
433         glyphsetCache[i-1].next = -1;
434         using_client_side_fonts = 1;
435
436         if(!X11DRV_XRender_Installed) {
437             TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
438             if(screen_depth <= 8 || !client_side_antialias_with_core)
439                 antialias = 0;
440         } else {
441             if(screen_depth <= 8 || !client_side_antialias_with_render)
442                 antialias = 0;
443         }
444     }
445     else TRACE("Using X11 core fonts\n");
446 }
447
448 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
449 static void get_xrender_color(const WineXRenderFormat *wxr_format, int src_color, XRenderColor *dst_color)
450 {
451     XRenderPictFormat *pf = wxr_format->pict_format;
452
453     if(pf->direct.redMask)
454         dst_color->red = ((src_color >> pf->direct.red) & pf->direct.redMask) * 65535/pf->direct.redMask;
455     else
456        dst_color->red = 0;
457
458     if(pf->direct.greenMask)
459         dst_color->green = ((src_color >> pf->direct.green) & pf->direct.greenMask) * 65535/pf->direct.greenMask;
460     else
461         dst_color->green = 0;
462
463     if(pf->direct.blueMask)
464         dst_color->blue = ((src_color >> pf->direct.blue) & pf->direct.blueMask) * 65535/pf->direct.blueMask;
465     else
466         dst_color->blue = 0;
467
468     dst_color->alpha = 0xffff;
469 }
470
471 static const WineXRenderFormat *get_xrender_format(WXRFormat format)
472 {
473     int i;
474     for(i=0; i<WineXRenderFormatsListSize; i++)
475     {
476         if(wxr_formats[i].format == format)
477         {
478             TRACE("Returning wxr_format=%#x\n", format);
479             return &wxr_formats[i];
480         }
481     }
482     return NULL;
483 }
484
485 static const WineXRenderFormat *get_xrender_format_from_color_shifts(int depth, ColorShifts *shifts)
486 {
487     int redMask, greenMask, blueMask;
488     unsigned int i;
489
490     if(depth == 1)
491         return get_xrender_format(WXR_FORMAT_MONO);
492
493     /* physDevs of a depth <=8, don't have color_shifts set and XRender can't handle those except for 1-bit */
494     if(!shifts)
495         return default_format;
496
497     redMask   = shifts->physicalRed.max << shifts->physicalRed.shift;
498     greenMask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
499     blueMask  = shifts->physicalBlue.max << shifts->physicalBlue.shift;
500
501     /* Try to locate a format which matches the specification of the dibsection. */
502     for(i = 0; i < (sizeof(wxr_formats_template) / sizeof(wxr_formats_template[0])); i++)
503     {
504         if( depth     == wxr_formats_template[i].depth &&
505             redMask   == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
506             greenMask == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
507             blueMask  == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue) )
508
509         {
510             /* When we reach this stage the format was found in our template table but this doesn't mean that
511             * the Xserver also supports this format (e.g. its depth might be too low). The call below verifies that.
512             */
513             return get_xrender_format(wxr_formats_template[i].wxr_format);
514         }
515     }
516
517     /* This should not happen because when we reach 'shifts' must have been set and we only allows shifts which are backed by X */
518     ERR("No XRender format found!\n");
519     return NULL;
520 }
521
522 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
523 static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
524 {
525 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
526     XTransform xform = {{
527         { XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(xoffset) },
528         { XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(yoffset) },
529         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
530     }};
531
532     pXRenderSetPictureTransform(gdi_display, src_pict, &xform);
533 #endif
534 }
535
536 /* check if we can use repeating instead of scaling for the specified source DC */
537 static BOOL use_source_repeat( X11DRV_PDEVICE *physDev )
538 {
539     return (physDev->bitmap &&
540             physDev->drawable_rect.right - physDev->drawable_rect.left == 1 &&
541             physDev->drawable_rect.bottom - physDev->drawable_rect.top == 1);
542 }
543
544 static struct xrender_info *get_xrender_info(X11DRV_PDEVICE *physDev)
545 {
546     if(!physDev->xrender)
547     {
548         physDev->xrender = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev->xrender));
549
550         if(!physDev->xrender)
551         {
552             ERR("Unable to allocate XRENDERINFO!\n");
553             return NULL;
554         }
555         physDev->xrender->cache_index = -1;
556     }
557     if (!physDev->xrender->format)
558         physDev->xrender->format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
559
560     return physDev->xrender;
561 }
562
563 static Picture get_xrender_picture(X11DRV_PDEVICE *physDev)
564 {
565     struct xrender_info *info = get_xrender_info(physDev);
566     if (!info) return 0;
567
568     if (!info->pict && info->format)
569     {
570         XRenderPictureAttributes pa;
571         RGNDATA *clip = X11DRV_GetRegionData( physDev->region, 0 );
572
573         wine_tsx11_lock();
574         pa.subwindow_mode = IncludeInferiors;
575         info->pict = pXRenderCreatePicture(gdi_display, physDev->drawable, info->format->pict_format,
576                                            CPSubwindowMode, &pa);
577         if (info->pict && clip)
578             pXRenderSetPictureClipRectangles( gdi_display, info->pict,
579                                               physDev->dc_rect.left, physDev->dc_rect.top,
580                                               (XRectangle *)clip->Buffer, clip->rdh.nCount );
581         wine_tsx11_unlock();
582         TRACE("Allocing pict=%lx dc=%p drawable=%08lx\n", info->pict, physDev->hdc, physDev->drawable);
583         HeapFree( GetProcessHeap(), 0, clip );
584     }
585
586     return info->pict;
587 }
588
589 static Picture get_xrender_picture_source(X11DRV_PDEVICE *physDev, BOOL repeat)
590 {
591     struct xrender_info *info = get_xrender_info(physDev);
592     if (!info) return 0;
593
594     if (!info->pict_src && info->format)
595     {
596         XRenderPictureAttributes pa;
597
598         wine_tsx11_lock();
599         pa.subwindow_mode = IncludeInferiors;
600         pa.repeat = repeat ? RepeatNormal : RepeatNone;
601         info->pict_src = pXRenderCreatePicture(gdi_display, physDev->drawable, info->format->pict_format,
602                                                CPSubwindowMode|CPRepeat, &pa);
603         wine_tsx11_unlock();
604
605         TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
606               info->pict_src, physDev->hdc, physDev->drawable, pa.repeat);
607     }
608
609     return info->pict_src;
610 }
611
612 /* return a mask picture used to force alpha to 0 */
613 static Picture get_no_alpha_mask(void)
614 {
615     static Pixmap pixmap;
616     static Picture pict;
617
618     wine_tsx11_lock();
619     if (!pict)
620     {
621         const WineXRenderFormat *fmt = get_xrender_format( WXR_FORMAT_A8R8G8B8 );
622         XRenderPictureAttributes pa;
623         XRenderColor col;
624
625         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
626         pa.repeat = RepeatNormal;
627         pa.component_alpha = True;
628         pict = pXRenderCreatePicture( gdi_display, pixmap, fmt->pict_format,
629                                       CPRepeat|CPComponentAlpha, &pa );
630         col.red = col.green = col.blue = 0xffff;
631         col.alpha = 0;
632         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
633     }
634     wine_tsx11_unlock();
635     return pict;
636 }
637
638 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
639 {
640   if(p1->hash != p2->hash) return TRUE;
641   if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE;
642   if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE;
643   if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
644   return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName);
645 }
646
647 #if 0
648 static void walk_cache(void)
649 {
650   int i;
651
652   EnterCriticalSection(&xrender_cs);
653   for(i=mru; i >= 0; i = glyphsetCache[i].next)
654     TRACE("item %d\n", i);
655   LeaveCriticalSection(&xrender_cs);
656 }
657 #endif
658
659 static int LookupEntry(LFANDSIZE *plfsz)
660 {
661   int i, prev_i = -1;
662
663   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
664     TRACE("%d\n", i);
665     if(glyphsetCache[i].count == -1) { /* reached free list so stop */
666       i = -1;
667       break;
668     }
669
670     if(!fontcmp(&glyphsetCache[i].lfsz, plfsz)) {
671       glyphsetCache[i].count++;
672       if(prev_i >= 0) {
673         glyphsetCache[prev_i].next = glyphsetCache[i].next;
674         glyphsetCache[i].next = mru;
675         mru = i;
676       }
677       TRACE("found font in cache %d\n", i);
678       return i;
679     }
680     prev_i = i;
681   }
682   TRACE("font not in cache\n");
683   return -1;
684 }
685
686 static void FreeEntry(int entry)
687 {
688     int i, format;
689   
690     for(format = 0; format < AA_MAXVALUE; format++) {
691         gsCacheEntryFormat * formatEntry;
692
693         if( !glyphsetCache[entry].format[format] )
694             continue;
695
696         formatEntry = glyphsetCache[entry].format[format];
697
698         if(formatEntry->glyphset) {
699             wine_tsx11_lock();
700             pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
701             wine_tsx11_unlock();
702             formatEntry->glyphset = 0;
703         }
704         if(formatEntry->nrealized) {
705             HeapFree(GetProcessHeap(), 0, formatEntry->realized);
706             formatEntry->realized = NULL;
707             if(formatEntry->bitmaps) {
708                 for(i = 0; i < formatEntry->nrealized; i++)
709                     HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps[i]);
710                 HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps);
711                 formatEntry->bitmaps = NULL;
712             }
713             HeapFree(GetProcessHeap(), 0, formatEntry->gis);
714             formatEntry->gis = NULL;
715             formatEntry->nrealized = 0;
716         }
717
718         HeapFree(GetProcessHeap(), 0, formatEntry);
719         glyphsetCache[entry].format[format] = NULL;
720     }
721 }
722
723 static int AllocEntry(void)
724 {
725   int best = -1, prev_best = -1, i, prev_i = -1;
726
727   if(lastfree >= 0) {
728     assert(glyphsetCache[lastfree].count == -1);
729     glyphsetCache[lastfree].count = 1;
730     best = lastfree;
731     lastfree = glyphsetCache[lastfree].next;
732     assert(best != mru);
733     glyphsetCache[best].next = mru;
734     mru = best;
735
736     TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
737     return mru;
738   }
739
740   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
741     if(glyphsetCache[i].count == 0) {
742       best = i;
743       prev_best = prev_i;
744     }
745     prev_i = i;
746   }
747
748   if(best >= 0) {
749     TRACE("freeing unused glyphset at cache %d\n", best);
750     FreeEntry(best);
751     glyphsetCache[best].count = 1;
752     if(prev_best >= 0) {
753       glyphsetCache[prev_best].next = glyphsetCache[best].next;
754       glyphsetCache[best].next = mru;
755       mru = best;
756     } else {
757       assert(mru == best);
758     }
759     return mru;
760   }
761
762   TRACE("Growing cache\n");
763   
764   if (glyphsetCache)
765     glyphsetCache = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
766                               glyphsetCache,
767                               (glyphsetCacheSize + INIT_CACHE_SIZE)
768                               * sizeof(*glyphsetCache));
769   else
770     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
771                               (glyphsetCacheSize + INIT_CACHE_SIZE)
772                               * sizeof(*glyphsetCache));
773
774   for(best = i = glyphsetCacheSize; i < glyphsetCacheSize + INIT_CACHE_SIZE;
775       i++) {
776     glyphsetCache[i].next = i + 1;
777     glyphsetCache[i].count = -1;
778   }
779   glyphsetCache[i-1].next = -1;
780   glyphsetCacheSize += INIT_CACHE_SIZE;
781
782   lastfree = glyphsetCache[best].next;
783   glyphsetCache[best].count = 1;
784   glyphsetCache[best].next = mru;
785   mru = best;
786   TRACE("new free cache slot at %d\n", mru);
787   return mru;
788 }
789
790 static BOOL get_gasp_flags(X11DRV_PDEVICE *physDev, WORD *flags)
791 {
792     DWORD size;
793     WORD *gasp, *buffer;
794     WORD num_recs;
795     DWORD ppem;
796     TEXTMETRICW tm;
797
798     *flags = 0;
799
800     size = GetFontData(physDev->hdc, MS_GASP_TAG,  0, NULL, 0);
801     if(size == GDI_ERROR)
802         return FALSE;
803
804     gasp = buffer = HeapAlloc(GetProcessHeap(), 0, size);
805     GetFontData(physDev->hdc, MS_GASP_TAG,  0, gasp, size);
806
807     GetTextMetricsW(physDev->hdc, &tm);
808     ppem = abs(X11DRV_YWStoDS(physDev, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading));
809
810     gasp++;
811     num_recs = get_be_word(*gasp);
812     gasp++;
813     while(num_recs--)
814     {
815         *flags = get_be_word(*(gasp + 1));
816         if(ppem <= get_be_word(*gasp))
817             break;
818         gasp += 2;
819     }
820     TRACE("got flags %04x for ppem %d\n", *flags, ppem);
821
822     HeapFree(GetProcessHeap(), 0, buffer);
823     return TRUE;
824 }
825
826 static AA_Type get_antialias_type( X11DRV_PDEVICE *physDev, BOOL subpixel, BOOL hinter)
827 {
828     AA_Type ret;
829     WORD flags;
830     UINT font_smoothing_type, font_smoothing_orientation;
831
832     if (X11DRV_XRender_Installed && subpixel &&
833         SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE, 0, &font_smoothing_type, 0) &&
834         font_smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
835     {
836         if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION, 0,
837                                     &font_smoothing_orientation, 0) &&
838              font_smoothing_orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
839         {
840             ret = AA_BGR;
841         }
842         else
843             ret = AA_RGB;
844         /*FIXME
845           If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
846           But, Wine's subpixel rendering can support the portrait mode.
847          */
848     }
849     else if (!hinter || !get_gasp_flags(physDev, &flags) || flags & GASP_DOGRAY)
850         ret = AA_Grey;
851     else
852         ret = AA_None;
853
854     return ret;
855 }
856
857 static int GetCacheEntry(X11DRV_PDEVICE *physDev, LFANDSIZE *plfsz)
858 {
859     int ret;
860     int format;
861     gsCacheEntry *entry;
862     static int hinter = -1;
863     static int subpixel = -1;
864     BOOL font_smoothing;
865
866     if((ret = LookupEntry(plfsz)) != -1) return ret;
867
868     ret = AllocEntry();
869     entry = glyphsetCache + ret;
870     entry->lfsz = *plfsz;
871     for( format = 0; format < AA_MAXVALUE; format++ ) {
872         assert( !entry->format[format] );
873     }
874
875     if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY)
876     {
877         if(hinter == -1 || subpixel == -1)
878         {
879             RASTERIZER_STATUS status;
880             GetRasterizerCaps(&status, sizeof(status));
881             hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
882             subpixel = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
883         }
884
885         switch (plfsz->lf.lfQuality)
886         {
887             case ANTIALIASED_QUALITY:
888                 entry->aa_default = get_antialias_type( physDev, FALSE, hinter );
889                 break;
890             case CLEARTYPE_QUALITY:
891             case CLEARTYPE_NATURAL_QUALITY:
892                 entry->aa_default = get_antialias_type( physDev, subpixel, hinter );
893                 break;
894             case DEFAULT_QUALITY:
895             case DRAFT_QUALITY:
896             case PROOF_QUALITY:
897             default:
898                 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0) &&
899                      font_smoothing)
900                 {
901                     entry->aa_default = get_antialias_type( physDev, subpixel, hinter );
902                 }
903                 else
904                     entry->aa_default = AA_None;
905                 break;
906         }
907
908 #ifdef SONAME_LIBFONTCONFIG
909         if (fontconfig_installed)
910         {
911             FcPattern *match, *pattern = pFcPatternCreate();
912             FcResult result;
913             char family[LF_FACESIZE * 4];
914
915             WideCharToMultiByte( CP_UTF8, 0, plfsz->lf.lfFaceName, -1, family, sizeof(family), NULL, NULL );
916             pFcPatternAddString( pattern, FC_FAMILY, (FcChar8 *)family );
917             if (plfsz->lf.lfWeight != FW_DONTCARE)
918             {
919                 int weight;
920                 switch (plfsz->lf.lfWeight)
921                 {
922                 case FW_THIN:       weight = FC_WEIGHT_THIN; break;
923                 case FW_EXTRALIGHT: weight = FC_WEIGHT_EXTRALIGHT; break;
924                 case FW_LIGHT:      weight = FC_WEIGHT_LIGHT; break;
925                 case FW_NORMAL:     weight = FC_WEIGHT_NORMAL; break;
926                 case FW_MEDIUM:     weight = FC_WEIGHT_MEDIUM; break;
927                 case FW_SEMIBOLD:   weight = FC_WEIGHT_SEMIBOLD; break;
928                 case FW_BOLD:       weight = FC_WEIGHT_BOLD; break;
929                 case FW_EXTRABOLD:  weight = FC_WEIGHT_EXTRABOLD; break;
930                 case FW_HEAVY:      weight = FC_WEIGHT_HEAVY; break;
931                 default:            weight = (plfsz->lf.lfWeight - 80) / 4; break;
932                 }
933                 pFcPatternAddInteger( pattern, FC_WEIGHT, weight );
934             }
935             pFcPatternAddInteger( pattern, FC_SLANT, plfsz->lf.lfItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
936             pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
937             pFcDefaultSubstitute( pattern );
938             if ((match = pFcFontMatch( NULL, pattern, &result )))
939             {
940                 int rgba;
941                 FcBool antialias;
942
943                 if (pFcPatternGetBool( match, FC_ANTIALIAS, 0, &antialias ) != FcResultMatch)
944                     antialias = TRUE;
945                 if (pFcPatternGetInteger( match, FC_RGBA, 0, &rgba ) == FcResultMatch)
946                 {
947                     FcChar8 *file;
948                     if (pFcPatternGetString( match, FC_FILE, 0, &file ) != FcResultMatch) file = NULL;
949
950                     TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
951                            rgba, antialias, debugstr_w(plfsz->lf.lfFaceName), debugstr_a((char *)file) );
952
953                     switch (rgba)
954                     {
955                     case FC_RGBA_RGB:  entry->aa_default = AA_RGB; break;
956                     case FC_RGBA_BGR:  entry->aa_default = AA_BGR; break;
957                     case FC_RGBA_VRGB: entry->aa_default = AA_VRGB; break;
958                     case FC_RGBA_VBGR: entry->aa_default = AA_VBGR; break;
959                     case FC_RGBA_NONE: entry->aa_default = antialias ? AA_Grey : AA_None; break;
960                     }
961                 }
962                 pFcPatternDestroy( match );
963             }
964             pFcPatternDestroy( pattern );
965         }
966 #endif  /* SONAME_LIBFONTCONFIG */
967
968         /* now check Xft resources */
969         {
970             char *value;
971             BOOL antialias = TRUE;
972
973             wine_tsx11_lock();
974             if ((value = XGetDefault( gdi_display, "Xft", "antialias" )))
975             {
976                 if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
977                     value[0] == '0' || !strcasecmp( value, "off" ))
978                     antialias = FALSE;
979             }
980             if ((value = XGetDefault( gdi_display, "Xft", "rgba" )))
981             {
982                 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value, antialias );
983                 if (!strcmp( value, "rgb" )) entry->aa_default = AA_RGB;
984                 else if (!strcmp( value, "bgr" )) entry->aa_default = AA_BGR;
985                 else if (!strcmp( value, "vrgb" )) entry->aa_default = AA_VRGB;
986                 else if (!strcmp( value, "vbgr" )) entry->aa_default = AA_VBGR;
987                 else if (!strcmp( value, "none" )) entry->aa_default = antialias ? AA_Grey : AA_None;
988             }
989             wine_tsx11_unlock();
990         }
991
992         /* we can't support subpixel without xrender */
993         if (!X11DRV_XRender_Installed && entry->aa_default > AA_Grey) entry->aa_default = AA_Grey;
994     }
995     else
996         entry->aa_default = AA_None;
997
998     return ret;
999 }
1000
1001 static void dec_ref_cache(int index)
1002 {
1003     assert(index >= 0);
1004     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
1005     assert(glyphsetCache[index].count > 0);
1006     glyphsetCache[index].count--;
1007 }
1008
1009 static void lfsz_calc_hash(LFANDSIZE *plfsz)
1010 {
1011   DWORD hash = 0, *ptr, two_chars;
1012   WORD *pwc;
1013   int i;
1014
1015   hash ^= plfsz->devsize.cx;
1016   hash ^= plfsz->devsize.cy;
1017   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
1018     hash ^= *ptr;
1019   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
1020     hash ^= *ptr;
1021   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
1022     two_chars = *ptr;
1023     pwc = (WCHAR *)&two_chars;
1024     if(!*pwc) break;
1025     *pwc = toupperW(*pwc);
1026     pwc++;
1027     *pwc = toupperW(*pwc);
1028     hash ^= two_chars;
1029     if(!*pwc) break;
1030   }
1031   plfsz->hash = hash;
1032   return;
1033 }
1034
1035 /***********************************************************************
1036  *   X11DRV_XRender_Finalize
1037  */
1038 void X11DRV_XRender_Finalize(void)
1039 {
1040     int i;
1041
1042     EnterCriticalSection(&xrender_cs);
1043     for(i = mru; i >= 0; i = glyphsetCache[i].next)
1044         FreeEntry(i);
1045     LeaveCriticalSection(&xrender_cs);
1046 }
1047
1048
1049 /***********************************************************************
1050  *   X11DRV_XRender_SelectFont
1051  */
1052 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
1053 {
1054     LFANDSIZE lfsz;
1055     struct xrender_info *info;
1056
1057     GetObjectW(hfont, sizeof(lfsz.lf), &lfsz.lf);
1058     TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1059           lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
1060           lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
1061     lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
1062     lfsz.devsize.cx = X11DRV_XWStoDS( physDev, lfsz.lf.lfWidth );
1063     lfsz.devsize.cy = X11DRV_YWStoDS( physDev, lfsz.lf.lfHeight );
1064     GetWorldTransform( physDev->hdc, &lfsz.xform );
1065     lfsz_calc_hash(&lfsz);
1066
1067     info = get_xrender_info(physDev);
1068     if (!info) return 0;
1069
1070     EnterCriticalSection(&xrender_cs);
1071     if(info->cache_index != -1)
1072         dec_ref_cache(info->cache_index);
1073     info->cache_index = GetCacheEntry(physDev, &lfsz);
1074     LeaveCriticalSection(&xrender_cs);
1075     return 0;
1076 }
1077
1078 /***********************************************************************
1079 *   X11DRV_XRender_SetDeviceClipping
1080 */
1081 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
1082 {
1083     if (physDev->xrender->pict)
1084     {
1085         wine_tsx11_lock();
1086         pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
1087                                           physDev->dc_rect.left, physDev->dc_rect.top,
1088                                           (XRectangle *)data->Buffer, data->rdh.nCount );
1089         wine_tsx11_unlock();
1090     }
1091 }
1092
1093 /***********************************************************************
1094  *   X11DRV_XRender_DeleteDC
1095  */
1096 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
1097 {
1098     X11DRV_XRender_UpdateDrawable(physDev);
1099
1100     EnterCriticalSection(&xrender_cs);
1101     if(physDev->xrender->cache_index != -1)
1102         dec_ref_cache(physDev->xrender->cache_index);
1103     LeaveCriticalSection(&xrender_cs);
1104
1105     HeapFree(GetProcessHeap(), 0, physDev->xrender);
1106     physDev->xrender = NULL;
1107     return;
1108 }
1109
1110 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
1111 {
1112     const WineXRenderFormat *fmt;
1113     ColorShifts shifts;
1114
1115     /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1116      * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1117      * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1118     if (!X11DRV_XRender_Installed || bits_pixel <= 8)
1119         return FALSE;
1120
1121     if (dib)
1122     {
1123         X11DRV_PALETTE_ComputeColorShifts(&shifts, dib->dsBitfields[0], dib->dsBitfields[1], dib->dsBitfields[2]);
1124         fmt = get_xrender_format_from_color_shifts(dib->dsBm.bmBitsPixel, &shifts);
1125
1126         /* Common formats should be in our picture format table. */
1127         if (!fmt)
1128         {
1129             TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1130                 dib->dsBm.bmBitsPixel, dib->dsBitfields[0], dib->dsBitfields[1], dib->dsBitfields[2]);
1131             return FALSE;
1132         }
1133     }
1134     else
1135     {
1136         int red_mask, green_mask, blue_mask;
1137
1138         /* We are dealing with a DDB */
1139         switch (bits_pixel)
1140         {
1141             case 16:
1142                 fmt = get_xrender_format(WXR_FORMAT_R5G6B5);
1143                 break;
1144             case 24:
1145                 fmt = get_xrender_format(WXR_FORMAT_R8G8B8);
1146                 break;
1147             case 32:
1148                 fmt = get_xrender_format(WXR_FORMAT_A8R8G8B8);
1149                 break;
1150             default:
1151                 fmt = NULL;
1152         }
1153
1154         if (!fmt)
1155         {
1156             TRACE("Unhandled DDB bits_pixel=%d\n", bits_pixel);
1157             return FALSE;
1158         }
1159
1160         red_mask = fmt->pict_format->direct.redMask << fmt->pict_format->direct.red;
1161         green_mask = fmt->pict_format->direct.greenMask << fmt->pict_format->direct.green;
1162         blue_mask = fmt->pict_format->direct.blueMask << fmt->pict_format->direct.blue;
1163         X11DRV_PALETTE_ComputeColorShifts(&shifts, red_mask, green_mask, blue_mask);
1164     }
1165
1166     physBitmap->pixmap_depth = fmt->pict_format->depth;
1167     physBitmap->trueColor = TRUE;
1168     physBitmap->pixmap_color_shifts = shifts;
1169     return TRUE;
1170 }
1171
1172 /***********************************************************************
1173  *   X11DRV_XRender_UpdateDrawable
1174  *
1175  * Deletes the pict and tile when the drawable changes.
1176  */
1177 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
1178 {
1179     struct xrender_info *info = physDev->xrender;
1180
1181     if (info->pict || info->pict_src)
1182     {
1183         wine_tsx11_lock();
1184         XFlush( gdi_display );
1185         if (info->pict)
1186         {
1187             TRACE("freeing pict = %lx dc = %p\n", info->pict, physDev->hdc);
1188             pXRenderFreePicture(gdi_display, info->pict);
1189             info->pict = 0;
1190         }
1191         if(info->pict_src)
1192         {
1193             TRACE("freeing pict = %lx dc = %p\n", info->pict_src, physDev->hdc);
1194             pXRenderFreePicture(gdi_display, info->pict_src);
1195             info->pict_src = 0;
1196         }
1197         wine_tsx11_unlock();
1198     }
1199
1200     info->format = NULL;
1201 }
1202
1203 /************************************************************************
1204  *   UploadGlyph
1205  *
1206  * Helper to ExtTextOut.  Must be called inside xrender_cs
1207  */
1208 static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
1209 {
1210     unsigned int buflen;
1211     char *buf;
1212     Glyph gid;
1213     GLYPHMETRICS gm;
1214     XGlyphInfo gi;
1215     gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
1216     gsCacheEntryFormat *formatEntry;
1217     UINT ggo_format = GGO_GLYPH_INDEX;
1218     WXRFormat wxr_format;
1219     static const char zero[4];
1220     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1221
1222     switch(format) {
1223     case AA_Grey:
1224         ggo_format |= WINE_GGO_GRAY16_BITMAP;
1225         break;
1226     case AA_RGB:
1227         ggo_format |= WINE_GGO_HRGB_BITMAP;
1228         break;
1229     case AA_BGR:
1230         ggo_format |= WINE_GGO_HBGR_BITMAP;
1231         break;
1232     case AA_VRGB:
1233         ggo_format |= WINE_GGO_VRGB_BITMAP;
1234         break;
1235     case AA_VBGR:
1236         ggo_format |= WINE_GGO_VBGR_BITMAP;
1237         break;
1238
1239     default:
1240         ERR("aa = %d - not implemented\n", format);
1241     case AA_None:
1242         ggo_format |= GGO_BITMAP;
1243         break;
1244     }
1245
1246     buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1247     if(buflen == GDI_ERROR) {
1248         if(format != AA_None) {
1249             format = AA_None;
1250             entry->aa_default = AA_None;
1251             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1252             buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1253         }
1254         if(buflen == GDI_ERROR) {
1255             WARN("GetGlyphOutlineW failed\n");
1256             return FALSE;
1257         }
1258         TRACE("Turning off antialiasing for this monochrome font\n");
1259     }
1260
1261     /* If there is nothing for the current type, we create the entry. */
1262     if( !entry->format[format] ) {
1263         entry->format[format] = HeapAlloc(GetProcessHeap(),
1264                                           HEAP_ZERO_MEMORY,
1265                                           sizeof(gsCacheEntryFormat));
1266     }
1267     formatEntry = entry->format[format];
1268
1269     if(formatEntry->nrealized <= glyph) {
1270         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1271
1272         if (formatEntry->realized)
1273             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1274                                       HEAP_ZERO_MEMORY,
1275                                       formatEntry->realized,
1276                                       formatEntry->nrealized * sizeof(BOOL));
1277         else
1278             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1279                                       HEAP_ZERO_MEMORY,
1280                                       formatEntry->nrealized * sizeof(BOOL));
1281
1282         if(!X11DRV_XRender_Installed) {
1283           if (formatEntry->bitmaps)
1284             formatEntry->bitmaps = HeapReAlloc(GetProcessHeap(),
1285                                       HEAP_ZERO_MEMORY,
1286                                       formatEntry->bitmaps,
1287                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1288           else
1289             formatEntry->bitmaps = HeapAlloc(GetProcessHeap(),
1290                                       HEAP_ZERO_MEMORY,
1291                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1292         }
1293         if (formatEntry->gis)
1294             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1295                                    HEAP_ZERO_MEMORY,
1296                                    formatEntry->gis,
1297                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1298         else
1299             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1300                                    HEAP_ZERO_MEMORY,
1301                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1302     }
1303
1304
1305     if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
1306         switch(format) {
1307             case AA_Grey:
1308                 wxr_format = WXR_FORMAT_GRAY;
1309                 break;
1310
1311             case AA_RGB:
1312             case AA_BGR:
1313             case AA_VRGB:
1314             case AA_VBGR:
1315                 wxr_format = WXR_FORMAT_A8R8G8B8;
1316                 break;
1317
1318             default:
1319                 ERR("aa = %d - not implemented\n", format);
1320             case AA_None:
1321                 wxr_format = WXR_FORMAT_MONO;
1322                 break;
1323         }
1324
1325         wine_tsx11_lock();
1326         formatEntry->font_format = get_xrender_format(wxr_format);
1327         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format->pict_format);
1328         wine_tsx11_unlock();
1329     }
1330
1331
1332     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1333     GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1334     formatEntry->realized[glyph] = TRUE;
1335
1336     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1337           buflen,
1338           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1339           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1340
1341     gi.width = gm.gmBlackBoxX;
1342     gi.height = gm.gmBlackBoxY;
1343     gi.x = -gm.gmptGlyphOrigin.x;
1344     gi.y = gm.gmptGlyphOrigin.y;
1345     gi.xOff = gm.gmCellIncX;
1346     gi.yOff = gm.gmCellIncY;
1347
1348     if(TRACE_ON(xrender)) {
1349         int pitch, i, j;
1350         char output[300];
1351         unsigned char *line;
1352
1353         if(format == AA_None) {
1354             pitch = ((gi.width + 31) / 32) * 4;
1355             for(i = 0; i < gi.height; i++) {
1356                 line = (unsigned char*) buf + i * pitch;
1357                 output[0] = '\0';
1358                 for(j = 0; j < pitch * 8; j++) {
1359                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1360                 }
1361                 TRACE("%s\n", output);
1362             }
1363         } else {
1364             static const char blks[] = " .:;!o*#";
1365             char str[2];
1366
1367             str[1] = '\0';
1368             pitch = ((gi.width + 3) / 4) * 4;
1369             for(i = 0; i < gi.height; i++) {
1370                 line = (unsigned char*) buf + i * pitch;
1371                 output[0] = '\0';
1372                 for(j = 0; j < pitch; j++) {
1373                     str[0] = blks[line[j] >> 5];
1374                     strcat(output, str);
1375                 }
1376                 TRACE("%s\n", output);
1377             }
1378         }
1379     }
1380
1381
1382     if(formatEntry->glyphset) {
1383         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1384             unsigned char *byte = (unsigned char*) buf, c;
1385             int i = buflen;
1386
1387             while(i--) {
1388                 c = *byte;
1389
1390                 /* magic to flip bit order */
1391                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1392                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1393                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1394
1395                 *byte++ = c;
1396             }
1397         }
1398         else if ( format != AA_Grey &&
1399                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1400         {
1401             unsigned int i, *data = (unsigned int *)buf;
1402             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1403         }
1404         gid = glyph;
1405
1406         /*
1407           XRenderCompositeText seems to ignore 0x0 glyphs when
1408           AA_None, which means we lose the advance width of glyphs
1409           like the space.  We'll pretend that such glyphs are 1x1
1410           bitmaps.
1411         */
1412
1413         if(buflen == 0)
1414             gi.width = gi.height = 1;
1415
1416         wine_tsx11_lock();
1417         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1418                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1419         wine_tsx11_unlock();
1420         HeapFree(GetProcessHeap(), 0, buf);
1421     } else {
1422         formatEntry->bitmaps[glyph] = buf;
1423     }
1424
1425     formatEntry->gis[glyph] = gi;
1426
1427     return TRUE;
1428 }
1429
1430 static void SharpGlyphMono(X11DRV_PDEVICE *physDev, INT x, INT y,
1431                             void *bitmap, XGlyphInfo *gi)
1432 {
1433     unsigned char   *srcLine = bitmap, *src;
1434     unsigned char   bits, bitsMask;
1435     int             width = gi->width;
1436     int             stride = ((width + 31) & ~31) >> 3;
1437     int             height = gi->height;
1438     int             w;
1439     int             xspan, lenspan;
1440
1441     TRACE("%d, %d\n", x, y);
1442     x -= gi->x;
1443     y -= gi->y;
1444     while (height--)
1445     {
1446         src = srcLine;
1447         srcLine += stride;
1448         w = width;
1449         
1450         bitsMask = 0x80;    /* FreeType is always MSB first */
1451         bits = *src++;
1452         
1453         xspan = x;
1454         while (w)
1455         {
1456             if (bits & bitsMask)
1457             {
1458                 lenspan = 0;
1459                 do
1460                 {
1461                     lenspan++;
1462                     if (lenspan == w)
1463                         break;
1464                     bitsMask = bitsMask >> 1;
1465                     if (!bitsMask)
1466                     {
1467                         bits = *src++;
1468                         bitsMask = 0x80;
1469                     }
1470                 } while (bits & bitsMask);
1471                 XFillRectangle (gdi_display, physDev->drawable, 
1472                                 physDev->gc, xspan, y, lenspan, 1);
1473                 xspan += lenspan;
1474                 w -= lenspan;
1475             }
1476             else
1477             {
1478                 do
1479                 {
1480                     w--;
1481                     xspan++;
1482                     if (!w)
1483                         break;
1484                     bitsMask = bitsMask >> 1;
1485                     if (!bitsMask)
1486                     {
1487                         bits = *src++;
1488                         bitsMask = 0x80;
1489                     }
1490                 } while (!(bits & bitsMask));
1491             }
1492         }
1493         y++;
1494     }
1495 }
1496
1497 static void SharpGlyphGray(X11DRV_PDEVICE *physDev, INT x, INT y,
1498                             void *bitmap, XGlyphInfo *gi)
1499 {
1500     unsigned char   *srcLine = bitmap, *src, bits;
1501     int             width = gi->width;
1502     int             stride = ((width + 3) & ~3);
1503     int             height = gi->height;
1504     int             w;
1505     int             xspan, lenspan;
1506
1507     x -= gi->x;
1508     y -= gi->y;
1509     while (height--)
1510     {
1511         src = srcLine;
1512         srcLine += stride;
1513         w = width;
1514         
1515         bits = *src++;
1516         xspan = x;
1517         while (w)
1518         {
1519             if (bits >= 0x80)
1520             {
1521                 lenspan = 0;
1522                 do
1523                 {
1524                     lenspan++;
1525                     if (lenspan == w)
1526                         break;
1527                     bits = *src++;
1528                 } while (bits >= 0x80);
1529                 XFillRectangle (gdi_display, physDev->drawable, 
1530                                 physDev->gc, xspan, y, lenspan, 1);
1531                 xspan += lenspan;
1532                 w -= lenspan;
1533             }
1534             else
1535             {
1536                 do
1537                 {
1538                     w--;
1539                     xspan++;
1540                     if (!w)
1541                         break;
1542                     bits = *src++;
1543                 } while (bits < 0x80);
1544             }
1545         }
1546         y++;
1547     }
1548 }
1549
1550
1551 static void ExamineBitfield (DWORD mask, int *shift, int *len)
1552 {
1553     int s, l;
1554
1555     s = 0;
1556     while ((mask & 1) == 0)
1557     {
1558         mask >>= 1;
1559         s++;
1560     }
1561     l = 0;
1562     while ((mask & 1) == 1)
1563     {
1564         mask >>= 1;
1565         l++;
1566     }
1567     *shift = s;
1568     *len = l;
1569 }
1570
1571 static DWORD GetField (DWORD pixel, int shift, int len)
1572 {
1573     pixel = pixel & (((1 << (len)) - 1) << shift);
1574     pixel = pixel << (32 - (shift + len)) >> 24;
1575     while (len < 8)
1576     {
1577         pixel |= (pixel >> len);
1578         len <<= 1;
1579     }
1580     return pixel;
1581 }
1582
1583
1584 static DWORD PutField (DWORD pixel, int shift, int len)
1585 {
1586     shift = shift - (8 - len);
1587     if (len <= 8)
1588         pixel &= (((1 << len) - 1) << (8 - len));
1589     if (shift < 0)
1590         pixel >>= -shift;
1591     else
1592         pixel <<= shift;
1593     return pixel;
1594 }
1595
1596 static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInfo *gi,
1597                             int color)
1598 {
1599     int             r_shift, r_len;
1600     int             g_shift, g_len;
1601     int             b_shift, b_len;
1602     BYTE            *maskLine, *mask, m;
1603     int             maskStride;
1604     DWORD           pixel;
1605     int             width, height;
1606     int             w, tx;
1607     BYTE            src_r, src_g, src_b;
1608
1609     x -= gi->x;
1610     y -= gi->y;
1611     width = gi->width;
1612     height = gi->height;
1613
1614     maskLine = bitmap;
1615     maskStride = (width + 3) & ~3;
1616
1617     ExamineBitfield (image->red_mask, &r_shift, &r_len);
1618     ExamineBitfield (image->green_mask, &g_shift, &g_len);
1619     ExamineBitfield (image->blue_mask, &b_shift, &b_len);
1620
1621     src_r = GetField(color, r_shift, r_len);
1622     src_g = GetField(color, g_shift, g_len);
1623     src_b = GetField(color, b_shift, b_len);
1624     
1625     for(; height--; y++)
1626     {
1627         mask = maskLine;
1628         maskLine += maskStride;
1629         w = width;
1630         tx = x;
1631
1632         if(y < 0) continue;
1633         if(y >= image->height) break;
1634
1635         for(; w--; tx++)
1636         {
1637             if(tx >= image->width) break;
1638
1639             m = *mask++;
1640             if(tx < 0) continue;
1641
1642             if (m == 0xff)
1643                 XPutPixel (image, tx, y, color);
1644             else if (m)
1645             {
1646                 BYTE r, g, b;
1647
1648                 pixel = XGetPixel (image, tx, y);
1649
1650                 r = GetField(pixel, r_shift, r_len);
1651                 r = ((BYTE)~m * (WORD)r + (BYTE)m * (WORD)src_r) >> 8;
1652                 g = GetField(pixel, g_shift, g_len);
1653                 g = ((BYTE)~m * (WORD)g + (BYTE)m * (WORD)src_g) >> 8;
1654                 b = GetField(pixel, b_shift, b_len);
1655                 b = ((BYTE)~m * (WORD)b + (BYTE)m * (WORD)src_b) >> 8;
1656
1657                 pixel = (PutField (r, r_shift, r_len) |
1658                          PutField (g, g_shift, g_len) |
1659                          PutField (b, b_shift, b_len));
1660                 XPutPixel (image, tx, y, pixel);
1661             }
1662         }
1663     }
1664 }
1665
1666 /*************************************************************
1667  *                 get_tile_pict
1668  *
1669  * Returns an appropriate Picture for tiling the text colour.
1670  * Call and use result within the xrender_cs
1671  */
1672 static Picture get_tile_pict(const WineXRenderFormat *wxr_format, int text_pixel)
1673 {
1674     static struct
1675     {
1676         Pixmap xpm;
1677         Picture pict;
1678         int current_color;
1679     } tiles[WXR_NB_FORMATS], *tile;
1680     XRenderColor col;
1681
1682     tile = &tiles[wxr_format->format];
1683
1684     if(!tile->xpm)
1685     {
1686         XRenderPictureAttributes pa;
1687
1688         wine_tsx11_lock();
1689         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, wxr_format->pict_format->depth);
1690
1691         pa.repeat = RepeatNormal;
1692         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, wxr_format->pict_format, CPRepeat, &pa);
1693         wine_tsx11_unlock();
1694
1695         /* init current_color to something different from text_pixel */
1696         tile->current_color = ~text_pixel;
1697
1698         if(wxr_format->format == WXR_FORMAT_MONO)
1699         {
1700             /* for a 1bpp bitmap we always need a 1 in the tile */
1701             col.red = col.green = col.blue = 0;
1702             col.alpha = 0xffff;
1703             wine_tsx11_lock();
1704             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1705             wine_tsx11_unlock();
1706         }
1707     }
1708
1709     if(text_pixel != tile->current_color && wxr_format->format != WXR_FORMAT_MONO)
1710     {
1711         get_xrender_color(wxr_format, text_pixel, &col);
1712         wine_tsx11_lock();
1713         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1714         wine_tsx11_unlock();
1715         tile->current_color = text_pixel;
1716     }
1717     return tile->pict;
1718 }
1719
1720 /*************************************************************
1721  *                 get_mask_pict
1722  *
1723  * Returns an appropriate Picture for masking with the specified alpha.
1724  * Call and use result within the xrender_cs
1725  */
1726 static Picture get_mask_pict( int alpha )
1727 {
1728     static Pixmap pixmap;
1729     static Picture pict;
1730     static int current_alpha;
1731
1732     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1733
1734     if (!pixmap)
1735     {
1736         const WineXRenderFormat *fmt = get_xrender_format( WXR_FORMAT_A8R8G8B8 );
1737         XRenderPictureAttributes pa;
1738
1739         wine_tsx11_lock();
1740         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1741         pa.repeat = RepeatNormal;
1742         pict = pXRenderCreatePicture( gdi_display, pixmap, fmt->pict_format, CPRepeat, &pa );
1743         wine_tsx11_unlock();
1744         current_alpha = -1;
1745     }
1746
1747     if (alpha != current_alpha)
1748     {
1749         XRenderColor col;
1750         col.red = col.green = col.blue = 0;
1751         col.alpha = current_alpha = alpha;
1752         wine_tsx11_lock();
1753         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1754         wine_tsx11_unlock();
1755     }
1756     return pict;
1757 }
1758
1759 static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
1760 {
1761     return 1;
1762 }
1763
1764 /***********************************************************************
1765  *   X11DRV_XRender_ExtTextOut
1766  */
1767 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
1768                                 const RECT *lprect, LPCWSTR wstr, UINT count,
1769                                 const INT *lpDx )
1770 {
1771     XGCValues xgcval;
1772     gsCacheEntry *entry;
1773     gsCacheEntryFormat *formatEntry;
1774     BOOL retv = FALSE;
1775     int textPixel, backgroundPixel;
1776     HRGN saved_region = 0;
1777     BOOL disable_antialias = FALSE;
1778     AA_Type aa_type = AA_None;
1779     DIBSECTION bmp;
1780     unsigned int idx;
1781     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
1782     Picture tile_pict = 0;
1783
1784     /* Do we need to disable antialiasing because of palette mode? */
1785     if( !physDev->bitmap || GetObjectW( physDev->bitmap->hbitmap, sizeof(bmp), &bmp ) != sizeof(bmp) ) {
1786         TRACE("bitmap is not a DIB\n");
1787     }
1788     else if (bmp.dsBmih.biBitCount <= 8) {
1789         TRACE("Disabling antialiasing\n");
1790         disable_antialias = TRUE;
1791     }
1792
1793     xgcval.function = GXcopy;
1794     xgcval.background = physDev->backgroundPixel;
1795     xgcval.fill_style = FillSolid;
1796     wine_tsx11_lock();
1797     XChangeGC( gdi_display, physDev->gc, GCFunction | GCBackground | GCFillStyle, &xgcval );
1798     wine_tsx11_unlock();
1799
1800     X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1801
1802     if(physDev->depth == 1) {
1803         if((physDev->textPixel & 0xffffff) == 0) {
1804             textPixel = 0;
1805             backgroundPixel = 1;
1806         } else {
1807             textPixel = 1;
1808             backgroundPixel = 0;
1809         }
1810     } else {
1811         textPixel = physDev->textPixel;
1812         backgroundPixel = physDev->backgroundPixel;
1813     }
1814
1815     if(flags & ETO_OPAQUE)
1816     {
1817         wine_tsx11_lock();
1818         XSetForeground( gdi_display, physDev->gc, backgroundPixel );
1819         XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1820                         physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top,
1821                         lprect->right - lprect->left, lprect->bottom - lprect->top );
1822         wine_tsx11_unlock();
1823     }
1824
1825     if(count == 0)
1826     {
1827         retv = TRUE;
1828         goto done_unlock;
1829     }
1830
1831     if (flags & ETO_CLIPPED)
1832     {
1833         HRGN clip_region;
1834
1835         clip_region = CreateRectRgnIndirect( lprect );
1836         /* make a copy of the current device region */
1837         saved_region = CreateRectRgn( 0, 0, 0, 0 );
1838         CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
1839         X11DRV_SetDeviceClipping( physDev, saved_region, clip_region );
1840         DeleteObject( clip_region );
1841     }
1842
1843     EnterCriticalSection(&xrender_cs);
1844
1845     entry = glyphsetCache + physDev->xrender->cache_index;
1846     if( disable_antialias == FALSE )
1847         aa_type = entry->aa_default;
1848     formatEntry = entry->format[aa_type];
1849
1850     for(idx = 0; idx < count; idx++) {
1851         if( !formatEntry ) {
1852             UploadGlyph(physDev, wstr[idx], aa_type);
1853             /* re-evaluate antialias since aa_default may have changed */
1854             if( disable_antialias == FALSE )
1855                 aa_type = entry->aa_default;
1856             formatEntry = entry->format[aa_type];
1857         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1858             UploadGlyph(physDev, wstr[idx], aa_type);
1859         }
1860     }
1861     if (!formatEntry)
1862     {
1863         WARN("could not upload requested glyphs\n");
1864         LeaveCriticalSection(&xrender_cs);
1865         goto done_unlock;
1866     }
1867
1868     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1869           physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1870
1871     if(X11DRV_XRender_Installed)
1872     {
1873         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1874         POINT offset = {0, 0};
1875         POINT desired, current;
1876         int render_op = PictOpOver;
1877         Picture pict = get_xrender_picture(physDev);
1878
1879         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1880            So we pass zeros to the function and move to our starting position using the first
1881            element of the elts array. */
1882
1883         desired.x = physDev->dc_rect.left + x;
1884         desired.y = physDev->dc_rect.top + y;
1885         current.x = current.y = 0;
1886
1887         tile_pict = get_tile_pict(dst_format, physDev->textPixel);
1888
1889         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1890          */
1891         if((dst_format->format == WXR_FORMAT_MONO) && (textPixel == 0))
1892             render_op = PictOpOutReverse; /* This gives us 'black' text */
1893
1894         for(idx = 0; idx < count; idx++)
1895         {
1896             elts[idx].glyphset = formatEntry->glyphset;
1897             elts[idx].chars = wstr + idx;
1898             elts[idx].nchars = 1;
1899             elts[idx].xOff = desired.x - current.x;
1900             elts[idx].yOff = desired.y - current.y;
1901
1902             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1903             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1904
1905             if(!lpDx)
1906             {
1907                 desired.x += formatEntry->gis[wstr[idx]].xOff;
1908                 desired.y += formatEntry->gis[wstr[idx]].yOff;
1909             }
1910             else
1911             {
1912                 if(flags & ETO_PDY)
1913                 {
1914                     offset.x += lpDx[idx * 2];
1915                     offset.y += lpDx[idx * 2 + 1];
1916                 }
1917                 else
1918                     offset.x += lpDx[idx];
1919                 desired.x = physDev->dc_rect.left + x + offset.x;
1920                 desired.y = physDev->dc_rect.top  + y + offset.y;
1921             }
1922         }
1923         wine_tsx11_lock();
1924         /* Make sure we don't have any transforms set from a previous call */
1925         set_xrender_transformation(pict, 1, 1, 0, 0);
1926         pXRenderCompositeText16(gdi_display, render_op,
1927                                 tile_pict,
1928                                 pict,
1929                                 formatEntry->font_format->pict_format,
1930                                 0, 0, 0, 0, elts, count);
1931         wine_tsx11_unlock();
1932         HeapFree(GetProcessHeap(), 0, elts);
1933     } else {
1934         POINT offset = {0, 0};
1935         wine_tsx11_lock();
1936         XSetForeground( gdi_display, physDev->gc, textPixel );
1937
1938         if(aa_type == AA_None || physDev->depth == 1)
1939         {
1940             void (* sharp_glyph_fn)(X11DRV_PDEVICE *, INT, INT, void *, XGlyphInfo *);
1941
1942             if(aa_type == AA_None)
1943                 sharp_glyph_fn = SharpGlyphMono;
1944             else
1945                 sharp_glyph_fn = SharpGlyphGray;
1946
1947             for(idx = 0; idx < count; idx++) {
1948                 sharp_glyph_fn(physDev,
1949                                physDev->dc_rect.left + x + offset.x,
1950                                physDev->dc_rect.top  + y + offset.y,
1951                                formatEntry->bitmaps[wstr[idx]],
1952                                &formatEntry->gis[wstr[idx]]);
1953                 if(lpDx)
1954                 {
1955                     if(flags & ETO_PDY)
1956                     {
1957                         offset.x += lpDx[idx * 2];
1958                         offset.y += lpDx[idx * 2 + 1];
1959                     }
1960                     else
1961                         offset.x += lpDx[idx];
1962                 }
1963                 else
1964                 {
1965                     offset.x += formatEntry->gis[wstr[idx]].xOff;
1966                     offset.y += formatEntry->gis[wstr[idx]].yOff;
1967                 }
1968             }
1969         } else {
1970             XImage *image;
1971             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
1972             RECT extents = {0, 0, 0, 0};
1973             POINT cur = {0, 0};
1974             int w = physDev->drawable_rect.right - physDev->drawable_rect.left;
1975             int h = physDev->drawable_rect.bottom - physDev->drawable_rect.top;
1976
1977             TRACE("drawable %dx%d\n", w, h);
1978
1979             for(idx = 0; idx < count; idx++) {
1980                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
1981                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
1982                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
1983                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
1984                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
1985                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
1986                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
1987                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
1988
1989                 if(lpDx)
1990                 {
1991                     if(flags & ETO_PDY)
1992                     {
1993                         cur.x += lpDx[idx * 2];
1994                         cur.y += lpDx[idx * 2 + 1];
1995                     }
1996                     else
1997                         cur.x += lpDx[idx];
1998                 }
1999                 else
2000                 {
2001                     cur.x += formatEntry->gis[wstr[idx]].xOff;
2002                     cur.y += formatEntry->gis[wstr[idx]].yOff;
2003                 }
2004             }
2005             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
2006                   extents.right, extents.bottom, physDev->dc_rect.left + x, physDev->dc_rect.top + y);
2007
2008             if(physDev->dc_rect.left + x + extents.left >= 0) {
2009                 image_x = physDev->dc_rect.left + x + extents.left;
2010                 image_off_x = 0;
2011             } else {
2012                 image_x = 0;
2013                 image_off_x = physDev->dc_rect.left + x + extents.left;
2014             }
2015             if(physDev->dc_rect.top + y + extents.top >= 0) {
2016                 image_y = physDev->dc_rect.top + y + extents.top;
2017                 image_off_y = 0;
2018             } else {
2019                 image_y = 0;
2020                 image_off_y = physDev->dc_rect.top + y + extents.top;
2021             }
2022             if(physDev->dc_rect.left + x + extents.right < w)
2023                 image_w = physDev->dc_rect.left + x + extents.right - image_x;
2024             else
2025                 image_w = w - image_x;
2026             if(physDev->dc_rect.top + y + extents.bottom < h)
2027                 image_h = physDev->dc_rect.top + y + extents.bottom - image_y;
2028             else
2029                 image_h = h - image_y;
2030
2031             if(image_w <= 0 || image_h <= 0) goto no_image;
2032
2033             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2034             image = XGetImage(gdi_display, physDev->drawable,
2035                               image_x, image_y, image_w, image_h,
2036                               AllPlanes, ZPixmap);
2037             X11DRV_check_error();
2038
2039             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2040                   gdi_display, (int)physDev->drawable, image_x, image_y,
2041                   image_w, image_h, AllPlanes, ZPixmap,
2042                   physDev->depth, image);
2043             if(!image) {
2044                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
2045                                            physDev->depth);
2046                 GC gc;
2047                 XGCValues gcv;
2048
2049                 gcv.graphics_exposures = False;
2050                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
2051                 XCopyArea(gdi_display, physDev->drawable, xpm, gc, image_x, image_y,
2052                           image_w, image_h, 0, 0);
2053                 XFreeGC(gdi_display, gc);
2054                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2055                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
2056                                   ZPixmap);
2057                 X11DRV_check_error();
2058                 XFreePixmap(gdi_display, xpm);
2059             }
2060             if(!image) goto no_image;
2061
2062             image->red_mask = visual->red_mask;
2063             image->green_mask = visual->green_mask;
2064             image->blue_mask = visual->blue_mask;
2065
2066             for(idx = 0; idx < count; idx++) {
2067                 SmoothGlyphGray(image,
2068                                 offset.x + image_off_x - extents.left,
2069                                 offset.y + image_off_y - extents.top,
2070                                 formatEntry->bitmaps[wstr[idx]],
2071                                 &formatEntry->gis[wstr[idx]],
2072                                 physDev->textPixel);
2073                 if(lpDx)
2074                 {
2075                     if(flags & ETO_PDY)
2076                     {
2077                         offset.x += lpDx[idx * 2];
2078                         offset.y += lpDx[idx * 2 + 1];
2079                     }
2080                     else
2081                         offset.x += lpDx[idx];
2082                 }
2083                 else
2084                 {
2085                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2086                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2087                 }
2088             }
2089             XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
2090                       image_x, image_y, image_w, image_h);
2091             XDestroyImage(image);
2092         }
2093     no_image:
2094         wine_tsx11_unlock();
2095     }
2096     LeaveCriticalSection(&xrender_cs);
2097
2098     if (flags & ETO_CLIPPED)
2099     {
2100         /* restore the device region */
2101         X11DRV_SetDeviceClipping( physDev, saved_region, 0 );
2102         DeleteObject( saved_region );
2103     }
2104
2105     retv = TRUE;
2106
2107 done_unlock:
2108     X11DRV_UnlockDIBSection( physDev, TRUE );
2109     return retv;
2110 }
2111
2112 /* Helper function for (stretched) blitting using xrender */
2113 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
2114                           int x_src, int y_src, int x_dst, int y_dst,
2115                           double xscale, double yscale, int width, int height )
2116 {
2117     int x_offset, y_offset;
2118
2119     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2120      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2121      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2122     if(xscale != 1.0 || yscale != 1.0)
2123     {
2124         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2125          * in the wrong quadrant of the x-y plane.
2126          */
2127         x_offset = (xscale < 0) ? -width : 0;
2128         y_offset = (yscale < 0) ? -height : 0;
2129         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2130     }
2131     else
2132     {
2133         x_offset = x_src;
2134         y_offset = y_src;
2135         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2136     }
2137     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
2138                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
2139 }
2140
2141 /* Helper function for (stretched) mono->color blitting using xrender */
2142 static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_pict,
2143                                int x_src, int y_src, double xscale, double yscale, int width, int height )
2144 {
2145     int x_offset, y_offset;
2146
2147     /* When doing a mono->color blit, 'src_pict' contains a 1x1 picture for tiling, the actual
2148      * source data is in mask_pict.  The 'src_pict' data effectively acts as an alpha channel to the
2149      * tile data. We need PictOpOver for correct rendering.
2150      * Note since the 'source data' is in the mask picture, we have to pass x_src / y_src using
2151      * mask_x / mask_y
2152      */
2153     if (xscale != 1.0 || yscale != 1.0)
2154     {
2155         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2156          * in the wrong quadrant of the x-y plane.
2157          */
2158         x_offset = (xscale < 0) ? -width : 0;
2159         y_offset = (yscale < 0) ? -height : 0;
2160         set_xrender_transformation(mask_pict, xscale, yscale, x_src, y_src);
2161     }
2162     else
2163     {
2164         x_offset = x_src;
2165         y_offset = y_src;
2166         set_xrender_transformation(mask_pict, 1, 1, 0, 0);
2167     }
2168     pXRenderComposite(gdi_display, PictOpOver, src_pict, mask_pict, dst_pict,
2169                       0, 0, x_offset, y_offset, 0, 0, width, height);
2170 }
2171
2172 /******************************************************************************
2173  * AlphaBlend
2174  */
2175 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2176                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2177 {
2178     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2179     struct xrender_info *src_info = get_xrender_info( devSrc );
2180     double xscale, yscale;
2181     BOOL use_repeat;
2182
2183     if(!X11DRV_XRender_Installed) {
2184         FIXME("Unable to AlphaBlend without Xrender\n");
2185         return FALSE;
2186     }
2187
2188     if (devSrc != devDst) X11DRV_LockDIBSection( devSrc, DIB_Status_GdiMod );
2189     X11DRV_LockDIBSection( devDst, DIB_Status_GdiMod );
2190
2191     dst_pict = get_xrender_picture( devDst );
2192
2193     use_repeat = use_source_repeat( devSrc );
2194     if (!use_repeat)
2195     {
2196         xscale = src->width / (double)dst->width;
2197         yscale = src->height / (double)dst->height;
2198     }
2199     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2200
2201     if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && src_info->format)
2202     {
2203         /* we need a source picture with no alpha */
2204         WXRFormat format = get_format_without_alpha( src_info->format->format );
2205         if (format != src_info->format->format)
2206         {
2207             XRenderPictureAttributes pa;
2208             const WineXRenderFormat *fmt = get_xrender_format( format );
2209
2210             wine_tsx11_lock();
2211             pa.subwindow_mode = IncludeInferiors;
2212             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2213             tmp_pict = pXRenderCreatePicture( gdi_display, devSrc->drawable, fmt->pict_format,
2214                                               CPSubwindowMode|CPRepeat, &pa );
2215             wine_tsx11_unlock();
2216             src_pict = tmp_pict;
2217         }
2218     }
2219
2220     if (!src_pict) src_pict = get_xrender_picture_source( devSrc, use_repeat );
2221
2222     EnterCriticalSection( &xrender_cs );
2223     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2224
2225     wine_tsx11_lock();
2226     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2227                   devSrc->dc_rect.left + src->visrect.left, devSrc->dc_rect.top + src->visrect.top,
2228                   devDst->dc_rect.left + dst->visrect.left, devDst->dc_rect.top + dst->visrect.top,
2229                   xscale, yscale,
2230                   dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top );
2231     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2232     wine_tsx11_unlock();
2233
2234     LeaveCriticalSection( &xrender_cs );
2235     if (devSrc != devDst) X11DRV_UnlockDIBSection( devSrc, FALSE );
2236     X11DRV_UnlockDIBSection( devDst, TRUE );
2237     return TRUE;
2238 }
2239
2240
2241 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2242 {
2243     /* At depths >1, the depth of physBitmap and physDev might not be the same e.g. the physbitmap might be a 16-bit DIB while the physdev uses 24-bit */
2244     int depth = physBitmap->pixmap_depth == 1 ? 1 : physDev->depth;
2245     const WineXRenderFormat *src_format = get_xrender_format_from_color_shifts(physBitmap->pixmap_depth, &physBitmap->pixmap_color_shifts);
2246     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
2247
2248     wine_tsx11_lock();
2249     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, depth);
2250
2251     /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2252     if( (physBitmap->pixmap_depth == 1) || (!X11DRV_XRender_Installed && physDev->depth == physBitmap->pixmap_depth) ||
2253         (src_format->format == dst_format->format) )
2254     {
2255         XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2256                    get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2257     }
2258     else /* We need depth conversion */
2259     {
2260         Picture src_pict, dst_pict;
2261         XRenderPictureAttributes pa;
2262         pa.subwindow_mode = IncludeInferiors;
2263         pa.repeat = RepeatNone;
2264
2265         src_pict = pXRenderCreatePicture(gdi_display, physBitmap->pixmap, src_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2266         dst_pict = pXRenderCreatePicture(gdi_display, physDev->brush.pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2267
2268         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, width, height);
2269         pXRenderFreePicture(gdi_display, src_pict);
2270         pXRenderFreePicture(gdi_display, dst_pict);
2271     }
2272     wine_tsx11_unlock();
2273 }
2274
2275 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2276                                       Pixmap pixmap, GC gc,
2277                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2278 {
2279     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2280     int width = dst->visrect.right - dst->visrect.left;
2281     int height = dst->visrect.bottom - dst->visrect.top;
2282     int x_src = physDevSrc->dc_rect.left + src->visrect.left;
2283     int y_src = physDevSrc->dc_rect.top + src->visrect.top;
2284     struct xrender_info *src_info = get_xrender_info(physDevSrc);
2285     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDevDst->depth, physDevDst->color_shifts);
2286     Picture src_pict=0, dst_pict=0, mask_pict=0;
2287     BOOL use_repeat;
2288     double xscale, yscale;
2289
2290     XRenderPictureAttributes pa;
2291     pa.subwindow_mode = IncludeInferiors;
2292     pa.repeat = RepeatNone;
2293
2294     TRACE("src depth=%d widthSrc=%d heightSrc=%d xSrc=%d ySrc=%d\n",
2295           physDevSrc->depth, src->width, src->height, x_src, y_src);
2296     TRACE("dst depth=%d widthDst=%d heightDst=%d\n", physDevDst->depth, dst->width, dst->height);
2297
2298     if(!X11DRV_XRender_Installed)
2299     {
2300         TRACE("Not using XRender since it is not available or disabled\n");
2301         return FALSE;
2302     }
2303
2304     /* XRender can't handle palettes, so abort */
2305     if(X11DRV_PALETTE_XPixelToPalette)
2306         return FALSE;
2307
2308     /* XRender is of no use in this case */
2309     if((physDevDst->depth == 1) && (physDevSrc->depth > 1))
2310         return FALSE;
2311
2312     /* Just use traditional X copy when the formats match and we don't need stretching */
2313     if((src_info->format->format == dst_format->format) && !stretch)
2314     {
2315         TRACE("Source and destination depth match and no stretching needed falling back to XCopyArea\n");
2316         wine_tsx11_lock();
2317         XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc, x_src, y_src, width, height, 0, 0);
2318         wine_tsx11_unlock();
2319         return TRUE;
2320     }
2321
2322     use_repeat = use_source_repeat( physDevSrc );
2323     if (!use_repeat)
2324     {
2325         xscale = src->width / (double)dst->width;
2326         yscale = src->height / (double)dst->height;
2327     }
2328     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2329
2330     /* mono -> color */
2331     if(physDevSrc->depth == 1 && physDevDst->depth > 1)
2332     {
2333         XRenderColor col;
2334         get_xrender_color(dst_format, physDevDst->textPixel, &col);
2335
2336         /* We use the source drawable as a mask */
2337         mask_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2338
2339         /* Use backgroundPixel as the foreground color */
2340         EnterCriticalSection( &xrender_cs );
2341         src_pict = get_tile_pict(dst_format, physDevDst->backgroundPixel);
2342
2343         /* Create a destination picture and fill it with textPixel color as the background color */
2344         wine_tsx11_lock();
2345         dst_pict = pXRenderCreatePicture(gdi_display, pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2346         pXRenderFillRectangle(gdi_display, PictOpSrc, dst_pict, &col, 0, 0, width, height);
2347
2348         xrender_mono_blit(src_pict, mask_pict, dst_pict, x_src, y_src, xscale, yscale, width, height);
2349
2350         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2351         wine_tsx11_unlock();
2352         LeaveCriticalSection( &xrender_cs );
2353     }
2354     else /* color -> color (can be at different depths) or mono -> mono */
2355     {
2356         if (physDevDst->depth == 32 && physDevSrc->depth < 32) mask_pict = get_no_alpha_mask();
2357         src_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2358
2359         wine_tsx11_lock();
2360         dst_pict = pXRenderCreatePicture(gdi_display,
2361                                           pixmap, dst_format->pict_format,
2362                                           CPSubwindowMode|CPRepeat, &pa);
2363
2364         xrender_blit(PictOpSrc, src_pict, mask_pict, dst_pict,
2365                      x_src, y_src, 0, 0, xscale, yscale, width, height);
2366
2367         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2368         wine_tsx11_unlock();
2369     }
2370     return TRUE;
2371 }
2372
2373 #else /* SONAME_LIBXRENDER */
2374
2375 void X11DRV_XRender_Init(void)
2376 {
2377     TRACE("XRender support not compiled in.\n");
2378     return;
2379 }
2380
2381 void X11DRV_XRender_Finalize(void)
2382 {
2383 }
2384
2385 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
2386 {
2387   assert(0);
2388   return FALSE;
2389 }
2390
2391 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
2392 {
2393   assert(0);
2394   return;
2395 }
2396
2397 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
2398 {
2399     assert(0);
2400     return;
2401 }
2402
2403 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
2404                                 const RECT *lprect, LPCWSTR wstr, UINT count,
2405                                 const INT *lpDx )
2406 {
2407   assert(0);
2408   return FALSE;
2409 }
2410
2411 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
2412 {
2413   assert(0);
2414   return;
2415 }
2416
2417 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2418                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2419 {
2420   FIXME("not supported - XRENDER headers were missing at compile time\n");
2421   return FALSE;
2422 }
2423
2424 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2425 {
2426     wine_tsx11_lock();
2427     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, physBitmap->pixmap_depth);
2428
2429     XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2430                get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2431     wine_tsx11_unlock();
2432 }
2433
2434 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2435 {
2436     return FALSE;
2437 }
2438
2439 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2440                                       Pixmap pixmap, GC gc,
2441                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2442 {
2443     return FALSE;
2444 }
2445 #endif /* SONAME_LIBXRENDER */