wined3d: Fix the EXT_blend_minmax extension definitions.
[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                 return ret;  /* ignore further configuration */
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         font_smoothing = TRUE;  /* default to enabled */
909 #ifdef SONAME_LIBFONTCONFIG
910         if (fontconfig_installed)
911         {
912             FcPattern *match, *pattern = pFcPatternCreate();
913             FcResult result;
914             char family[LF_FACESIZE * 4];
915
916             WideCharToMultiByte( CP_UTF8, 0, plfsz->lf.lfFaceName, -1, family, sizeof(family), NULL, NULL );
917             pFcPatternAddString( pattern, FC_FAMILY, (FcChar8 *)family );
918             if (plfsz->lf.lfWeight != FW_DONTCARE)
919             {
920                 int weight;
921                 switch (plfsz->lf.lfWeight)
922                 {
923                 case FW_THIN:       weight = FC_WEIGHT_THIN; break;
924                 case FW_EXTRALIGHT: weight = FC_WEIGHT_EXTRALIGHT; break;
925                 case FW_LIGHT:      weight = FC_WEIGHT_LIGHT; break;
926                 case FW_NORMAL:     weight = FC_WEIGHT_NORMAL; break;
927                 case FW_MEDIUM:     weight = FC_WEIGHT_MEDIUM; break;
928                 case FW_SEMIBOLD:   weight = FC_WEIGHT_SEMIBOLD; break;
929                 case FW_BOLD:       weight = FC_WEIGHT_BOLD; break;
930                 case FW_EXTRABOLD:  weight = FC_WEIGHT_EXTRABOLD; break;
931                 case FW_HEAVY:      weight = FC_WEIGHT_HEAVY; break;
932                 default:            weight = (plfsz->lf.lfWeight - 80) / 4; break;
933                 }
934                 pFcPatternAddInteger( pattern, FC_WEIGHT, weight );
935             }
936             pFcPatternAddInteger( pattern, FC_SLANT, plfsz->lf.lfItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
937             pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
938             pFcDefaultSubstitute( pattern );
939             if ((match = pFcFontMatch( NULL, pattern, &result )))
940             {
941                 int rgba;
942                 FcBool antialias;
943
944                 if (pFcPatternGetBool( match, FC_ANTIALIAS, 0, &antialias ) != FcResultMatch)
945                     antialias = TRUE;
946                 if (pFcPatternGetInteger( match, FC_RGBA, 0, &rgba ) == FcResultMatch)
947                 {
948                     FcChar8 *file;
949                     if (pFcPatternGetString( match, FC_FILE, 0, &file ) != FcResultMatch) file = NULL;
950
951                     TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
952                            rgba, antialias, debugstr_w(plfsz->lf.lfFaceName), debugstr_a((char *)file) );
953
954                     switch (rgba)
955                     {
956                     case FC_RGBA_RGB:  entry->aa_default = AA_RGB; break;
957                     case FC_RGBA_BGR:  entry->aa_default = AA_BGR; break;
958                     case FC_RGBA_VRGB: entry->aa_default = AA_VRGB; break;
959                     case FC_RGBA_VBGR: entry->aa_default = AA_VBGR; break;
960                     case FC_RGBA_NONE: entry->aa_default = AA_Grey; break;
961                     }
962                 }
963                 if (!antialias) font_smoothing = FALSE;
964                 pFcPatternDestroy( match );
965             }
966             pFcPatternDestroy( pattern );
967         }
968 #endif  /* SONAME_LIBFONTCONFIG */
969
970         /* now check Xft resources */
971         {
972             char *value;
973             BOOL antialias = TRUE;
974
975             wine_tsx11_lock();
976             if ((value = XGetDefault( gdi_display, "Xft", "antialias" )))
977             {
978                 if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
979                     value[0] == '0' || !strcasecmp( value, "off" ))
980                     antialias = FALSE;
981             }
982             if ((value = XGetDefault( gdi_display, "Xft", "rgba" )))
983             {
984                 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value, antialias );
985                 if (!strcmp( value, "rgb" )) entry->aa_default = AA_RGB;
986                 else if (!strcmp( value, "bgr" )) entry->aa_default = AA_BGR;
987                 else if (!strcmp( value, "vrgb" )) entry->aa_default = AA_VRGB;
988                 else if (!strcmp( value, "vbgr" )) entry->aa_default = AA_VBGR;
989                 else if (!strcmp( value, "none" )) entry->aa_default = AA_Grey;
990             }
991             wine_tsx11_unlock();
992             if (!antialias) font_smoothing = FALSE;
993         }
994
995         if (!font_smoothing) entry->aa_default = AA_None;
996
997         /* we can't support subpixel without xrender */
998         if (!X11DRV_XRender_Installed && entry->aa_default > AA_Grey) entry->aa_default = AA_Grey;
999     }
1000     else
1001         entry->aa_default = AA_None;
1002
1003     return ret;
1004 }
1005
1006 static void dec_ref_cache(int index)
1007 {
1008     assert(index >= 0);
1009     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
1010     assert(glyphsetCache[index].count > 0);
1011     glyphsetCache[index].count--;
1012 }
1013
1014 static void lfsz_calc_hash(LFANDSIZE *plfsz)
1015 {
1016   DWORD hash = 0, *ptr, two_chars;
1017   WORD *pwc;
1018   int i;
1019
1020   hash ^= plfsz->devsize.cx;
1021   hash ^= plfsz->devsize.cy;
1022   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
1023     hash ^= *ptr;
1024   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
1025     hash ^= *ptr;
1026   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
1027     two_chars = *ptr;
1028     pwc = (WCHAR *)&two_chars;
1029     if(!*pwc) break;
1030     *pwc = toupperW(*pwc);
1031     pwc++;
1032     *pwc = toupperW(*pwc);
1033     hash ^= two_chars;
1034     if(!*pwc) break;
1035   }
1036   plfsz->hash = hash;
1037   return;
1038 }
1039
1040 /***********************************************************************
1041  *   X11DRV_XRender_Finalize
1042  */
1043 void X11DRV_XRender_Finalize(void)
1044 {
1045     int i;
1046
1047     EnterCriticalSection(&xrender_cs);
1048     for(i = mru; i >= 0; i = glyphsetCache[i].next)
1049         FreeEntry(i);
1050     LeaveCriticalSection(&xrender_cs);
1051 }
1052
1053
1054 /***********************************************************************
1055  *   X11DRV_XRender_SelectFont
1056  */
1057 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
1058 {
1059     LFANDSIZE lfsz;
1060     struct xrender_info *info;
1061
1062     GetObjectW(hfont, sizeof(lfsz.lf), &lfsz.lf);
1063     TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1064           lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
1065           lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
1066     lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
1067     lfsz.devsize.cx = X11DRV_XWStoDS( physDev, lfsz.lf.lfWidth );
1068     lfsz.devsize.cy = X11DRV_YWStoDS( physDev, lfsz.lf.lfHeight );
1069
1070     GetTransform( physDev->hdc, 0x204, &lfsz.xform );
1071     TRACE("font transform %f %f %f %f\n", lfsz.xform.eM11, lfsz.xform.eM12,
1072           lfsz.xform.eM21, lfsz.xform.eM22);
1073
1074     /* Not used fields, would break hashing */
1075     lfsz.xform.eDx = lfsz.xform.eDy = 0;
1076
1077     lfsz_calc_hash(&lfsz);
1078
1079     info = get_xrender_info(physDev);
1080     if (!info) return 0;
1081
1082     EnterCriticalSection(&xrender_cs);
1083     if(info->cache_index != -1)
1084         dec_ref_cache(info->cache_index);
1085     info->cache_index = GetCacheEntry(physDev, &lfsz);
1086     LeaveCriticalSection(&xrender_cs);
1087     return 0;
1088 }
1089
1090 /***********************************************************************
1091 *   X11DRV_XRender_SetDeviceClipping
1092 */
1093 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
1094 {
1095     if (physDev->xrender->pict)
1096     {
1097         wine_tsx11_lock();
1098         pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
1099                                           physDev->dc_rect.left, physDev->dc_rect.top,
1100                                           (XRectangle *)data->Buffer, data->rdh.nCount );
1101         wine_tsx11_unlock();
1102     }
1103 }
1104
1105 /***********************************************************************
1106  *   X11DRV_XRender_DeleteDC
1107  */
1108 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
1109 {
1110     X11DRV_XRender_UpdateDrawable(physDev);
1111
1112     EnterCriticalSection(&xrender_cs);
1113     if(physDev->xrender->cache_index != -1)
1114         dec_ref_cache(physDev->xrender->cache_index);
1115     LeaveCriticalSection(&xrender_cs);
1116
1117     HeapFree(GetProcessHeap(), 0, physDev->xrender);
1118     physDev->xrender = NULL;
1119     return;
1120 }
1121
1122 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
1123 {
1124     const WineXRenderFormat *fmt;
1125     ColorShifts shifts;
1126
1127     /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1128      * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1129      * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1130     if (!X11DRV_XRender_Installed || bits_pixel <= 8)
1131         return FALSE;
1132
1133     if (dib)
1134     {
1135         X11DRV_PALETTE_ComputeColorShifts(&shifts, dib->dsBitfields[0], dib->dsBitfields[1], dib->dsBitfields[2]);
1136         fmt = get_xrender_format_from_color_shifts(dib->dsBm.bmBitsPixel, &shifts);
1137
1138         /* Common formats should be in our picture format table. */
1139         if (!fmt)
1140         {
1141             TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1142                 dib->dsBm.bmBitsPixel, dib->dsBitfields[0], dib->dsBitfields[1], dib->dsBitfields[2]);
1143             return FALSE;
1144         }
1145     }
1146     else
1147     {
1148         int red_mask, green_mask, blue_mask;
1149
1150         /* We are dealing with a DDB */
1151         switch (bits_pixel)
1152         {
1153             case 16:
1154                 fmt = get_xrender_format(WXR_FORMAT_R5G6B5);
1155                 break;
1156             case 24:
1157                 fmt = get_xrender_format(WXR_FORMAT_R8G8B8);
1158                 break;
1159             case 32:
1160                 fmt = get_xrender_format(WXR_FORMAT_A8R8G8B8);
1161                 break;
1162             default:
1163                 fmt = NULL;
1164         }
1165
1166         if (!fmt)
1167         {
1168             TRACE("Unhandled DDB bits_pixel=%d\n", bits_pixel);
1169             return FALSE;
1170         }
1171
1172         red_mask = fmt->pict_format->direct.redMask << fmt->pict_format->direct.red;
1173         green_mask = fmt->pict_format->direct.greenMask << fmt->pict_format->direct.green;
1174         blue_mask = fmt->pict_format->direct.blueMask << fmt->pict_format->direct.blue;
1175         X11DRV_PALETTE_ComputeColorShifts(&shifts, red_mask, green_mask, blue_mask);
1176     }
1177
1178     physBitmap->pixmap_depth = fmt->pict_format->depth;
1179     physBitmap->trueColor = TRUE;
1180     physBitmap->pixmap_color_shifts = shifts;
1181     return TRUE;
1182 }
1183
1184 /***********************************************************************
1185  *   X11DRV_XRender_UpdateDrawable
1186  *
1187  * Deletes the pict and tile when the drawable changes.
1188  */
1189 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
1190 {
1191     struct xrender_info *info = physDev->xrender;
1192
1193     if (info->pict || info->pict_src)
1194     {
1195         wine_tsx11_lock();
1196         XFlush( gdi_display );
1197         if (info->pict)
1198         {
1199             TRACE("freeing pict = %lx dc = %p\n", info->pict, physDev->hdc);
1200             pXRenderFreePicture(gdi_display, info->pict);
1201             info->pict = 0;
1202         }
1203         if(info->pict_src)
1204         {
1205             TRACE("freeing pict = %lx dc = %p\n", info->pict_src, physDev->hdc);
1206             pXRenderFreePicture(gdi_display, info->pict_src);
1207             info->pict_src = 0;
1208         }
1209         wine_tsx11_unlock();
1210     }
1211
1212     info->format = NULL;
1213 }
1214
1215 /************************************************************************
1216  *   UploadGlyph
1217  *
1218  * Helper to ExtTextOut.  Must be called inside xrender_cs
1219  */
1220 static void UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
1221 {
1222     unsigned int buflen;
1223     char *buf;
1224     Glyph gid;
1225     GLYPHMETRICS gm;
1226     XGlyphInfo gi;
1227     gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
1228     gsCacheEntryFormat *formatEntry;
1229     UINT ggo_format = GGO_GLYPH_INDEX;
1230     WXRFormat wxr_format;
1231     static const char zero[4];
1232     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1233
1234     switch(format) {
1235     case AA_Grey:
1236         ggo_format |= WINE_GGO_GRAY16_BITMAP;
1237         break;
1238     case AA_RGB:
1239         ggo_format |= WINE_GGO_HRGB_BITMAP;
1240         break;
1241     case AA_BGR:
1242         ggo_format |= WINE_GGO_HBGR_BITMAP;
1243         break;
1244     case AA_VRGB:
1245         ggo_format |= WINE_GGO_VRGB_BITMAP;
1246         break;
1247     case AA_VBGR:
1248         ggo_format |= WINE_GGO_VBGR_BITMAP;
1249         break;
1250
1251     default:
1252         ERR("aa = %d - not implemented\n", format);
1253     case AA_None:
1254         ggo_format |= GGO_BITMAP;
1255         break;
1256     }
1257
1258     buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1259     if(buflen == GDI_ERROR) {
1260         if(format != AA_None) {
1261             format = AA_None;
1262             entry->aa_default = AA_None;
1263             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1264             buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1265         }
1266         if(buflen == GDI_ERROR) {
1267             WARN("GetGlyphOutlineW failed using default glyph\n");
1268             buflen = GetGlyphOutlineW(physDev->hdc, 0, ggo_format, &gm, 0, NULL, &identity);
1269             if(buflen == GDI_ERROR) {
1270                 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1271                 buflen = GetGlyphOutlineW(physDev->hdc, 0x20, ggo_format, &gm, 0, NULL, &identity);
1272                 if(buflen == GDI_ERROR) {
1273                     ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1274                     return;
1275                 }
1276             }
1277         }
1278         TRACE("Turning off antialiasing for this monochrome font\n");
1279     }
1280
1281     /* If there is nothing for the current type, we create the entry. */
1282     if( !entry->format[format] ) {
1283         entry->format[format] = HeapAlloc(GetProcessHeap(),
1284                                           HEAP_ZERO_MEMORY,
1285                                           sizeof(gsCacheEntryFormat));
1286     }
1287     formatEntry = entry->format[format];
1288
1289     if(formatEntry->nrealized <= glyph) {
1290         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1291
1292         if (formatEntry->realized)
1293             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1294                                       HEAP_ZERO_MEMORY,
1295                                       formatEntry->realized,
1296                                       formatEntry->nrealized * sizeof(BOOL));
1297         else
1298             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1299                                       HEAP_ZERO_MEMORY,
1300                                       formatEntry->nrealized * sizeof(BOOL));
1301
1302         if(!X11DRV_XRender_Installed) {
1303           if (formatEntry->bitmaps)
1304             formatEntry->bitmaps = HeapReAlloc(GetProcessHeap(),
1305                                       HEAP_ZERO_MEMORY,
1306                                       formatEntry->bitmaps,
1307                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1308           else
1309             formatEntry->bitmaps = HeapAlloc(GetProcessHeap(),
1310                                       HEAP_ZERO_MEMORY,
1311                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1312         }
1313         if (formatEntry->gis)
1314             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1315                                    HEAP_ZERO_MEMORY,
1316                                    formatEntry->gis,
1317                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1318         else
1319             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1320                                    HEAP_ZERO_MEMORY,
1321                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1322     }
1323
1324
1325     if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
1326         switch(format) {
1327             case AA_Grey:
1328                 wxr_format = WXR_FORMAT_GRAY;
1329                 break;
1330
1331             case AA_RGB:
1332             case AA_BGR:
1333             case AA_VRGB:
1334             case AA_VBGR:
1335                 wxr_format = WXR_FORMAT_A8R8G8B8;
1336                 break;
1337
1338             default:
1339                 ERR("aa = %d - not implemented\n", format);
1340             case AA_None:
1341                 wxr_format = WXR_FORMAT_MONO;
1342                 break;
1343         }
1344
1345         wine_tsx11_lock();
1346         formatEntry->font_format = get_xrender_format(wxr_format);
1347         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format->pict_format);
1348         wine_tsx11_unlock();
1349     }
1350
1351
1352     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1353     GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1354     formatEntry->realized[glyph] = TRUE;
1355
1356     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1357           buflen,
1358           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1359           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1360
1361     gi.width = gm.gmBlackBoxX;
1362     gi.height = gm.gmBlackBoxY;
1363     gi.x = -gm.gmptGlyphOrigin.x;
1364     gi.y = gm.gmptGlyphOrigin.y;
1365     gi.xOff = gm.gmCellIncX;
1366     gi.yOff = gm.gmCellIncY;
1367
1368     if(TRACE_ON(xrender)) {
1369         int pitch, i, j;
1370         char output[300];
1371         unsigned char *line;
1372
1373         if(format == AA_None) {
1374             pitch = ((gi.width + 31) / 32) * 4;
1375             for(i = 0; i < gi.height; i++) {
1376                 line = (unsigned char*) buf + i * pitch;
1377                 output[0] = '\0';
1378                 for(j = 0; j < pitch * 8; j++) {
1379                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1380                 }
1381                 TRACE("%s\n", output);
1382             }
1383         } else {
1384             static const char blks[] = " .:;!o*#";
1385             char str[2];
1386
1387             str[1] = '\0';
1388             pitch = ((gi.width + 3) / 4) * 4;
1389             for(i = 0; i < gi.height; i++) {
1390                 line = (unsigned char*) buf + i * pitch;
1391                 output[0] = '\0';
1392                 for(j = 0; j < pitch; j++) {
1393                     str[0] = blks[line[j] >> 5];
1394                     strcat(output, str);
1395                 }
1396                 TRACE("%s\n", output);
1397             }
1398         }
1399     }
1400
1401
1402     if(formatEntry->glyphset) {
1403         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1404             unsigned char *byte = (unsigned char*) buf, c;
1405             int i = buflen;
1406
1407             while(i--) {
1408                 c = *byte;
1409
1410                 /* magic to flip bit order */
1411                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1412                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1413                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1414
1415                 *byte++ = c;
1416             }
1417         }
1418         else if ( format != AA_Grey &&
1419                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1420         {
1421             unsigned int i, *data = (unsigned int *)buf;
1422             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1423         }
1424         gid = glyph;
1425
1426         /*
1427           XRenderCompositeText seems to ignore 0x0 glyphs when
1428           AA_None, which means we lose the advance width of glyphs
1429           like the space.  We'll pretend that such glyphs are 1x1
1430           bitmaps.
1431         */
1432
1433         if(buflen == 0)
1434             gi.width = gi.height = 1;
1435
1436         wine_tsx11_lock();
1437         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1438                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1439         wine_tsx11_unlock();
1440         HeapFree(GetProcessHeap(), 0, buf);
1441     } else {
1442         formatEntry->bitmaps[glyph] = buf;
1443     }
1444
1445     formatEntry->gis[glyph] = gi;
1446 }
1447
1448 static void SharpGlyphMono(X11DRV_PDEVICE *physDev, INT x, INT y,
1449                             void *bitmap, XGlyphInfo *gi)
1450 {
1451     unsigned char   *srcLine = bitmap, *src;
1452     unsigned char   bits, bitsMask;
1453     int             width = gi->width;
1454     int             stride = ((width + 31) & ~31) >> 3;
1455     int             height = gi->height;
1456     int             w;
1457     int             xspan, lenspan;
1458
1459     TRACE("%d, %d\n", x, y);
1460     x -= gi->x;
1461     y -= gi->y;
1462     while (height--)
1463     {
1464         src = srcLine;
1465         srcLine += stride;
1466         w = width;
1467         
1468         bitsMask = 0x80;    /* FreeType is always MSB first */
1469         bits = *src++;
1470         
1471         xspan = x;
1472         while (w)
1473         {
1474             if (bits & bitsMask)
1475             {
1476                 lenspan = 0;
1477                 do
1478                 {
1479                     lenspan++;
1480                     if (lenspan == w)
1481                         break;
1482                     bitsMask = bitsMask >> 1;
1483                     if (!bitsMask)
1484                     {
1485                         bits = *src++;
1486                         bitsMask = 0x80;
1487                     }
1488                 } while (bits & bitsMask);
1489                 XFillRectangle (gdi_display, physDev->drawable, 
1490                                 physDev->gc, xspan, y, lenspan, 1);
1491                 xspan += lenspan;
1492                 w -= lenspan;
1493             }
1494             else
1495             {
1496                 do
1497                 {
1498                     w--;
1499                     xspan++;
1500                     if (!w)
1501                         break;
1502                     bitsMask = bitsMask >> 1;
1503                     if (!bitsMask)
1504                     {
1505                         bits = *src++;
1506                         bitsMask = 0x80;
1507                     }
1508                 } while (!(bits & bitsMask));
1509             }
1510         }
1511         y++;
1512     }
1513 }
1514
1515 static void SharpGlyphGray(X11DRV_PDEVICE *physDev, INT x, INT y,
1516                             void *bitmap, XGlyphInfo *gi)
1517 {
1518     unsigned char   *srcLine = bitmap, *src, bits;
1519     int             width = gi->width;
1520     int             stride = ((width + 3) & ~3);
1521     int             height = gi->height;
1522     int             w;
1523     int             xspan, lenspan;
1524
1525     x -= gi->x;
1526     y -= gi->y;
1527     while (height--)
1528     {
1529         src = srcLine;
1530         srcLine += stride;
1531         w = width;
1532         
1533         bits = *src++;
1534         xspan = x;
1535         while (w)
1536         {
1537             if (bits >= 0x80)
1538             {
1539                 lenspan = 0;
1540                 do
1541                 {
1542                     lenspan++;
1543                     if (lenspan == w)
1544                         break;
1545                     bits = *src++;
1546                 } while (bits >= 0x80);
1547                 XFillRectangle (gdi_display, physDev->drawable, 
1548                                 physDev->gc, xspan, y, lenspan, 1);
1549                 xspan += lenspan;
1550                 w -= lenspan;
1551             }
1552             else
1553             {
1554                 do
1555                 {
1556                     w--;
1557                     xspan++;
1558                     if (!w)
1559                         break;
1560                     bits = *src++;
1561                 } while (bits < 0x80);
1562             }
1563         }
1564         y++;
1565     }
1566 }
1567
1568
1569 static void ExamineBitfield (DWORD mask, int *shift, int *len)
1570 {
1571     int s, l;
1572
1573     s = 0;
1574     while ((mask & 1) == 0)
1575     {
1576         mask >>= 1;
1577         s++;
1578     }
1579     l = 0;
1580     while ((mask & 1) == 1)
1581     {
1582         mask >>= 1;
1583         l++;
1584     }
1585     *shift = s;
1586     *len = l;
1587 }
1588
1589 static DWORD GetField (DWORD pixel, int shift, int len)
1590 {
1591     pixel = pixel & (((1 << (len)) - 1) << shift);
1592     pixel = pixel << (32 - (shift + len)) >> 24;
1593     while (len < 8)
1594     {
1595         pixel |= (pixel >> len);
1596         len <<= 1;
1597     }
1598     return pixel;
1599 }
1600
1601
1602 static DWORD PutField (DWORD pixel, int shift, int len)
1603 {
1604     shift = shift - (8 - len);
1605     if (len <= 8)
1606         pixel &= (((1 << len) - 1) << (8 - len));
1607     if (shift < 0)
1608         pixel >>= -shift;
1609     else
1610         pixel <<= shift;
1611     return pixel;
1612 }
1613
1614 static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInfo *gi,
1615                             int color)
1616 {
1617     int             r_shift, r_len;
1618     int             g_shift, g_len;
1619     int             b_shift, b_len;
1620     BYTE            *maskLine, *mask, m;
1621     int             maskStride;
1622     DWORD           pixel;
1623     int             width, height;
1624     int             w, tx;
1625     BYTE            src_r, src_g, src_b;
1626
1627     x -= gi->x;
1628     y -= gi->y;
1629     width = gi->width;
1630     height = gi->height;
1631
1632     maskLine = bitmap;
1633     maskStride = (width + 3) & ~3;
1634
1635     ExamineBitfield (image->red_mask, &r_shift, &r_len);
1636     ExamineBitfield (image->green_mask, &g_shift, &g_len);
1637     ExamineBitfield (image->blue_mask, &b_shift, &b_len);
1638
1639     src_r = GetField(color, r_shift, r_len);
1640     src_g = GetField(color, g_shift, g_len);
1641     src_b = GetField(color, b_shift, b_len);
1642     
1643     for(; height--; y++)
1644     {
1645         mask = maskLine;
1646         maskLine += maskStride;
1647         w = width;
1648         tx = x;
1649
1650         if(y < 0) continue;
1651         if(y >= image->height) break;
1652
1653         for(; w--; tx++)
1654         {
1655             if(tx >= image->width) break;
1656
1657             m = *mask++;
1658             if(tx < 0) continue;
1659
1660             if (m == 0xff)
1661                 XPutPixel (image, tx, y, color);
1662             else if (m)
1663             {
1664                 BYTE r, g, b;
1665
1666                 pixel = XGetPixel (image, tx, y);
1667
1668                 r = GetField(pixel, r_shift, r_len);
1669                 r = ((BYTE)~m * (WORD)r + (BYTE)m * (WORD)src_r) >> 8;
1670                 g = GetField(pixel, g_shift, g_len);
1671                 g = ((BYTE)~m * (WORD)g + (BYTE)m * (WORD)src_g) >> 8;
1672                 b = GetField(pixel, b_shift, b_len);
1673                 b = ((BYTE)~m * (WORD)b + (BYTE)m * (WORD)src_b) >> 8;
1674
1675                 pixel = (PutField (r, r_shift, r_len) |
1676                          PutField (g, g_shift, g_len) |
1677                          PutField (b, b_shift, b_len));
1678                 XPutPixel (image, tx, y, pixel);
1679             }
1680         }
1681     }
1682 }
1683
1684 /*************************************************************
1685  *                 get_tile_pict
1686  *
1687  * Returns an appropriate Picture for tiling the text colour.
1688  * Call and use result within the xrender_cs
1689  */
1690 static Picture get_tile_pict(const WineXRenderFormat *wxr_format, int text_pixel)
1691 {
1692     static struct
1693     {
1694         Pixmap xpm;
1695         Picture pict;
1696         int current_color;
1697     } tiles[WXR_NB_FORMATS], *tile;
1698     XRenderColor col;
1699
1700     tile = &tiles[wxr_format->format];
1701
1702     if(!tile->xpm)
1703     {
1704         XRenderPictureAttributes pa;
1705
1706         wine_tsx11_lock();
1707         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, wxr_format->pict_format->depth);
1708
1709         pa.repeat = RepeatNormal;
1710         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, wxr_format->pict_format, CPRepeat, &pa);
1711         wine_tsx11_unlock();
1712
1713         /* init current_color to something different from text_pixel */
1714         tile->current_color = ~text_pixel;
1715
1716         if(wxr_format->format == WXR_FORMAT_MONO)
1717         {
1718             /* for a 1bpp bitmap we always need a 1 in the tile */
1719             col.red = col.green = col.blue = 0;
1720             col.alpha = 0xffff;
1721             wine_tsx11_lock();
1722             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1723             wine_tsx11_unlock();
1724         }
1725     }
1726
1727     if(text_pixel != tile->current_color && wxr_format->format != WXR_FORMAT_MONO)
1728     {
1729         get_xrender_color(wxr_format, text_pixel, &col);
1730         wine_tsx11_lock();
1731         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1732         wine_tsx11_unlock();
1733         tile->current_color = text_pixel;
1734     }
1735     return tile->pict;
1736 }
1737
1738 /*************************************************************
1739  *                 get_mask_pict
1740  *
1741  * Returns an appropriate Picture for masking with the specified alpha.
1742  * Call and use result within the xrender_cs
1743  */
1744 static Picture get_mask_pict( int alpha )
1745 {
1746     static Pixmap pixmap;
1747     static Picture pict;
1748     static int current_alpha;
1749
1750     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1751
1752     if (!pixmap)
1753     {
1754         const WineXRenderFormat *fmt = get_xrender_format( WXR_FORMAT_A8R8G8B8 );
1755         XRenderPictureAttributes pa;
1756
1757         wine_tsx11_lock();
1758         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1759         pa.repeat = RepeatNormal;
1760         pict = pXRenderCreatePicture( gdi_display, pixmap, fmt->pict_format, CPRepeat, &pa );
1761         wine_tsx11_unlock();
1762         current_alpha = -1;
1763     }
1764
1765     if (alpha != current_alpha)
1766     {
1767         XRenderColor col;
1768         col.red = col.green = col.blue = 0;
1769         col.alpha = current_alpha = alpha;
1770         wine_tsx11_lock();
1771         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1772         wine_tsx11_unlock();
1773     }
1774     return pict;
1775 }
1776
1777 static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
1778 {
1779     return 1;
1780 }
1781
1782 /***********************************************************************
1783  *   X11DRV_XRender_ExtTextOut
1784  */
1785 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
1786                                 const RECT *lprect, LPCWSTR wstr, UINT count,
1787                                 const INT *lpDx )
1788 {
1789     XGCValues xgcval;
1790     gsCacheEntry *entry;
1791     gsCacheEntryFormat *formatEntry;
1792     BOOL retv = FALSE;
1793     int textPixel, backgroundPixel;
1794     HRGN saved_region = 0;
1795     BOOL disable_antialias = FALSE;
1796     AA_Type aa_type = AA_None;
1797     DIBSECTION bmp;
1798     unsigned int idx;
1799     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
1800     Picture tile_pict = 0;
1801
1802     /* Do we need to disable antialiasing because of palette mode? */
1803     if( !physDev->bitmap || GetObjectW( physDev->bitmap->hbitmap, sizeof(bmp), &bmp ) != sizeof(bmp) ) {
1804         TRACE("bitmap is not a DIB\n");
1805     }
1806     else if (bmp.dsBmih.biBitCount <= 8) {
1807         TRACE("Disabling antialiasing\n");
1808         disable_antialias = TRUE;
1809     }
1810
1811     xgcval.function = GXcopy;
1812     xgcval.background = physDev->backgroundPixel;
1813     xgcval.fill_style = FillSolid;
1814     wine_tsx11_lock();
1815     XChangeGC( gdi_display, physDev->gc, GCFunction | GCBackground | GCFillStyle, &xgcval );
1816     wine_tsx11_unlock();
1817
1818     X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1819
1820     if(physDev->depth == 1) {
1821         if((physDev->textPixel & 0xffffff) == 0) {
1822             textPixel = 0;
1823             backgroundPixel = 1;
1824         } else {
1825             textPixel = 1;
1826             backgroundPixel = 0;
1827         }
1828     } else {
1829         textPixel = physDev->textPixel;
1830         backgroundPixel = physDev->backgroundPixel;
1831     }
1832
1833     if(flags & ETO_OPAQUE)
1834     {
1835         wine_tsx11_lock();
1836         XSetForeground( gdi_display, physDev->gc, backgroundPixel );
1837         XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1838                         physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top,
1839                         lprect->right - lprect->left, lprect->bottom - lprect->top );
1840         wine_tsx11_unlock();
1841     }
1842
1843     if(count == 0)
1844     {
1845         retv = TRUE;
1846         goto done_unlock;
1847     }
1848
1849     if (flags & ETO_CLIPPED)
1850     {
1851         HRGN clip_region;
1852
1853         clip_region = CreateRectRgnIndirect( lprect );
1854         /* make a copy of the current device region */
1855         saved_region = CreateRectRgn( 0, 0, 0, 0 );
1856         CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
1857         X11DRV_SetDeviceClipping( physDev, saved_region, clip_region );
1858         DeleteObject( clip_region );
1859     }
1860
1861     EnterCriticalSection(&xrender_cs);
1862
1863     entry = glyphsetCache + physDev->xrender->cache_index;
1864     if( disable_antialias == FALSE )
1865         aa_type = entry->aa_default;
1866     formatEntry = entry->format[aa_type];
1867
1868     for(idx = 0; idx < count; idx++) {
1869         if( !formatEntry ) {
1870             UploadGlyph(physDev, wstr[idx], aa_type);
1871             /* re-evaluate antialias since aa_default may have changed */
1872             if( disable_antialias == FALSE )
1873                 aa_type = entry->aa_default;
1874             formatEntry = entry->format[aa_type];
1875         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1876             UploadGlyph(physDev, wstr[idx], aa_type);
1877         }
1878     }
1879     if (!formatEntry)
1880     {
1881         WARN("could not upload requested glyphs\n");
1882         LeaveCriticalSection(&xrender_cs);
1883         goto done_unlock;
1884     }
1885
1886     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1887           physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1888
1889     if(X11DRV_XRender_Installed)
1890     {
1891         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1892         POINT offset = {0, 0};
1893         POINT desired, current;
1894         int render_op = PictOpOver;
1895         Picture pict = get_xrender_picture(physDev);
1896
1897         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1898            So we pass zeros to the function and move to our starting position using the first
1899            element of the elts array. */
1900
1901         desired.x = physDev->dc_rect.left + x;
1902         desired.y = physDev->dc_rect.top + y;
1903         current.x = current.y = 0;
1904
1905         tile_pict = get_tile_pict(dst_format, physDev->textPixel);
1906
1907         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1908          */
1909         if((dst_format->format == WXR_FORMAT_MONO) && (textPixel == 0))
1910             render_op = PictOpOutReverse; /* This gives us 'black' text */
1911
1912         for(idx = 0; idx < count; idx++)
1913         {
1914             elts[idx].glyphset = formatEntry->glyphset;
1915             elts[idx].chars = wstr + idx;
1916             elts[idx].nchars = 1;
1917             elts[idx].xOff = desired.x - current.x;
1918             elts[idx].yOff = desired.y - current.y;
1919
1920             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1921             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1922
1923             if(!lpDx)
1924             {
1925                 desired.x += formatEntry->gis[wstr[idx]].xOff;
1926                 desired.y += formatEntry->gis[wstr[idx]].yOff;
1927             }
1928             else
1929             {
1930                 if(flags & ETO_PDY)
1931                 {
1932                     offset.x += lpDx[idx * 2];
1933                     offset.y += lpDx[idx * 2 + 1];
1934                 }
1935                 else
1936                     offset.x += lpDx[idx];
1937                 desired.x = physDev->dc_rect.left + x + offset.x;
1938                 desired.y = physDev->dc_rect.top  + y + offset.y;
1939             }
1940         }
1941         wine_tsx11_lock();
1942         /* Make sure we don't have any transforms set from a previous call */
1943         set_xrender_transformation(pict, 1, 1, 0, 0);
1944         pXRenderCompositeText16(gdi_display, render_op,
1945                                 tile_pict,
1946                                 pict,
1947                                 formatEntry->font_format->pict_format,
1948                                 0, 0, 0, 0, elts, count);
1949         wine_tsx11_unlock();
1950         HeapFree(GetProcessHeap(), 0, elts);
1951     } else {
1952         POINT offset = {0, 0};
1953         wine_tsx11_lock();
1954         XSetForeground( gdi_display, physDev->gc, textPixel );
1955
1956         if(aa_type == AA_None || physDev->depth == 1)
1957         {
1958             void (* sharp_glyph_fn)(X11DRV_PDEVICE *, INT, INT, void *, XGlyphInfo *);
1959
1960             if(aa_type == AA_None)
1961                 sharp_glyph_fn = SharpGlyphMono;
1962             else
1963                 sharp_glyph_fn = SharpGlyphGray;
1964
1965             for(idx = 0; idx < count; idx++) {
1966                 sharp_glyph_fn(physDev,
1967                                physDev->dc_rect.left + x + offset.x,
1968                                physDev->dc_rect.top  + y + offset.y,
1969                                formatEntry->bitmaps[wstr[idx]],
1970                                &formatEntry->gis[wstr[idx]]);
1971                 if(lpDx)
1972                 {
1973                     if(flags & ETO_PDY)
1974                     {
1975                         offset.x += lpDx[idx * 2];
1976                         offset.y += lpDx[idx * 2 + 1];
1977                     }
1978                     else
1979                         offset.x += lpDx[idx];
1980                 }
1981                 else
1982                 {
1983                     offset.x += formatEntry->gis[wstr[idx]].xOff;
1984                     offset.y += formatEntry->gis[wstr[idx]].yOff;
1985                 }
1986             }
1987         } else {
1988             XImage *image;
1989             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
1990             RECT extents = {0, 0, 0, 0};
1991             POINT cur = {0, 0};
1992             int w = physDev->drawable_rect.right - physDev->drawable_rect.left;
1993             int h = physDev->drawable_rect.bottom - physDev->drawable_rect.top;
1994
1995             TRACE("drawable %dx%d\n", w, h);
1996
1997             for(idx = 0; idx < count; idx++) {
1998                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
1999                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
2000                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
2001                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
2002                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
2003                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
2004                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
2005                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
2006
2007                 if(lpDx)
2008                 {
2009                     if(flags & ETO_PDY)
2010                     {
2011                         cur.x += lpDx[idx * 2];
2012                         cur.y += lpDx[idx * 2 + 1];
2013                     }
2014                     else
2015                         cur.x += lpDx[idx];
2016                 }
2017                 else
2018                 {
2019                     cur.x += formatEntry->gis[wstr[idx]].xOff;
2020                     cur.y += formatEntry->gis[wstr[idx]].yOff;
2021                 }
2022             }
2023             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
2024                   extents.right, extents.bottom, physDev->dc_rect.left + x, physDev->dc_rect.top + y);
2025
2026             if(physDev->dc_rect.left + x + extents.left >= 0) {
2027                 image_x = physDev->dc_rect.left + x + extents.left;
2028                 image_off_x = 0;
2029             } else {
2030                 image_x = 0;
2031                 image_off_x = physDev->dc_rect.left + x + extents.left;
2032             }
2033             if(physDev->dc_rect.top + y + extents.top >= 0) {
2034                 image_y = physDev->dc_rect.top + y + extents.top;
2035                 image_off_y = 0;
2036             } else {
2037                 image_y = 0;
2038                 image_off_y = physDev->dc_rect.top + y + extents.top;
2039             }
2040             if(physDev->dc_rect.left + x + extents.right < w)
2041                 image_w = physDev->dc_rect.left + x + extents.right - image_x;
2042             else
2043                 image_w = w - image_x;
2044             if(physDev->dc_rect.top + y + extents.bottom < h)
2045                 image_h = physDev->dc_rect.top + y + extents.bottom - image_y;
2046             else
2047                 image_h = h - image_y;
2048
2049             if(image_w <= 0 || image_h <= 0) goto no_image;
2050
2051             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2052             image = XGetImage(gdi_display, physDev->drawable,
2053                               image_x, image_y, image_w, image_h,
2054                               AllPlanes, ZPixmap);
2055             X11DRV_check_error();
2056
2057             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2058                   gdi_display, (int)physDev->drawable, image_x, image_y,
2059                   image_w, image_h, AllPlanes, ZPixmap,
2060                   physDev->depth, image);
2061             if(!image) {
2062                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
2063                                            physDev->depth);
2064                 GC gc;
2065                 XGCValues gcv;
2066
2067                 gcv.graphics_exposures = False;
2068                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
2069                 XCopyArea(gdi_display, physDev->drawable, xpm, gc, image_x, image_y,
2070                           image_w, image_h, 0, 0);
2071                 XFreeGC(gdi_display, gc);
2072                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2073                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
2074                                   ZPixmap);
2075                 X11DRV_check_error();
2076                 XFreePixmap(gdi_display, xpm);
2077             }
2078             if(!image) goto no_image;
2079
2080             image->red_mask = visual->red_mask;
2081             image->green_mask = visual->green_mask;
2082             image->blue_mask = visual->blue_mask;
2083
2084             for(idx = 0; idx < count; idx++) {
2085                 SmoothGlyphGray(image,
2086                                 offset.x + image_off_x - extents.left,
2087                                 offset.y + image_off_y - extents.top,
2088                                 formatEntry->bitmaps[wstr[idx]],
2089                                 &formatEntry->gis[wstr[idx]],
2090                                 physDev->textPixel);
2091                 if(lpDx)
2092                 {
2093                     if(flags & ETO_PDY)
2094                     {
2095                         offset.x += lpDx[idx * 2];
2096                         offset.y += lpDx[idx * 2 + 1];
2097                     }
2098                     else
2099                         offset.x += lpDx[idx];
2100                 }
2101                 else
2102                 {
2103                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2104                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2105                 }
2106             }
2107             XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
2108                       image_x, image_y, image_w, image_h);
2109             XDestroyImage(image);
2110         }
2111     no_image:
2112         wine_tsx11_unlock();
2113     }
2114     LeaveCriticalSection(&xrender_cs);
2115
2116     if (flags & ETO_CLIPPED)
2117     {
2118         /* restore the device region */
2119         X11DRV_SetDeviceClipping( physDev, saved_region, 0 );
2120         DeleteObject( saved_region );
2121     }
2122
2123     retv = TRUE;
2124
2125 done_unlock:
2126     X11DRV_UnlockDIBSection( physDev, TRUE );
2127     return retv;
2128 }
2129
2130 /* Helper function for (stretched) blitting using xrender */
2131 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
2132                           int x_src, int y_src, int x_dst, int y_dst,
2133                           double xscale, double yscale, int width, int height )
2134 {
2135     int x_offset, y_offset;
2136
2137     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2138      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2139      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2140     if(xscale != 1.0 || yscale != 1.0)
2141     {
2142         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2143          * in the wrong quadrant of the x-y plane.
2144          */
2145         x_offset = (xscale < 0) ? -width : 0;
2146         y_offset = (yscale < 0) ? -height : 0;
2147         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2148     }
2149     else
2150     {
2151         x_offset = x_src;
2152         y_offset = y_src;
2153         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2154     }
2155     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
2156                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
2157 }
2158
2159 /* Helper function for (stretched) mono->color blitting using xrender */
2160 static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_pict,
2161                                int x_src, int y_src, double xscale, double yscale, int width, int height )
2162 {
2163     int x_offset, y_offset;
2164
2165     /* When doing a mono->color blit, 'src_pict' contains a 1x1 picture for tiling, the actual
2166      * source data is in mask_pict.  The 'src_pict' data effectively acts as an alpha channel to the
2167      * tile data. We need PictOpOver for correct rendering.
2168      * Note since the 'source data' is in the mask picture, we have to pass x_src / y_src using
2169      * mask_x / mask_y
2170      */
2171     if (xscale != 1.0 || yscale != 1.0)
2172     {
2173         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2174          * in the wrong quadrant of the x-y plane.
2175          */
2176         x_offset = (xscale < 0) ? -width : 0;
2177         y_offset = (yscale < 0) ? -height : 0;
2178         set_xrender_transformation(mask_pict, xscale, yscale, x_src, y_src);
2179     }
2180     else
2181     {
2182         x_offset = x_src;
2183         y_offset = y_src;
2184         set_xrender_transformation(mask_pict, 1, 1, 0, 0);
2185     }
2186     pXRenderComposite(gdi_display, PictOpOver, src_pict, mask_pict, dst_pict,
2187                       0, 0, x_offset, y_offset, 0, 0, width, height);
2188 }
2189
2190 /******************************************************************************
2191  * AlphaBlend
2192  */
2193 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2194                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2195 {
2196     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2197     struct xrender_info *src_info = get_xrender_info( devSrc );
2198     double xscale, yscale;
2199     BOOL use_repeat;
2200
2201     if(!X11DRV_XRender_Installed) {
2202         FIXME("Unable to AlphaBlend without Xrender\n");
2203         return FALSE;
2204     }
2205
2206     if (devSrc != devDst) X11DRV_LockDIBSection( devSrc, DIB_Status_GdiMod );
2207     X11DRV_LockDIBSection( devDst, DIB_Status_GdiMod );
2208
2209     dst_pict = get_xrender_picture( devDst );
2210
2211     use_repeat = use_source_repeat( devSrc );
2212     if (!use_repeat)
2213     {
2214         xscale = src->width / (double)dst->width;
2215         yscale = src->height / (double)dst->height;
2216     }
2217     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2218
2219     if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && src_info->format)
2220     {
2221         /* we need a source picture with no alpha */
2222         WXRFormat format = get_format_without_alpha( src_info->format->format );
2223         if (format != src_info->format->format)
2224         {
2225             XRenderPictureAttributes pa;
2226             const WineXRenderFormat *fmt = get_xrender_format( format );
2227
2228             wine_tsx11_lock();
2229             pa.subwindow_mode = IncludeInferiors;
2230             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2231             tmp_pict = pXRenderCreatePicture( gdi_display, devSrc->drawable, fmt->pict_format,
2232                                               CPSubwindowMode|CPRepeat, &pa );
2233             wine_tsx11_unlock();
2234             src_pict = tmp_pict;
2235         }
2236     }
2237
2238     if (!src_pict) src_pict = get_xrender_picture_source( devSrc, use_repeat );
2239
2240     EnterCriticalSection( &xrender_cs );
2241     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2242
2243     wine_tsx11_lock();
2244     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2245                   devSrc->dc_rect.left + src->visrect.left, devSrc->dc_rect.top + src->visrect.top,
2246                   devDst->dc_rect.left + dst->visrect.left, devDst->dc_rect.top + dst->visrect.top,
2247                   xscale, yscale,
2248                   dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top );
2249     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2250     wine_tsx11_unlock();
2251
2252     LeaveCriticalSection( &xrender_cs );
2253     if (devSrc != devDst) X11DRV_UnlockDIBSection( devSrc, FALSE );
2254     X11DRV_UnlockDIBSection( devDst, TRUE );
2255     return TRUE;
2256 }
2257
2258
2259 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2260 {
2261     /* 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 */
2262     int depth = physBitmap->pixmap_depth == 1 ? 1 : physDev->depth;
2263     const WineXRenderFormat *src_format = get_xrender_format_from_color_shifts(physBitmap->pixmap_depth, &physBitmap->pixmap_color_shifts);
2264     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
2265
2266     wine_tsx11_lock();
2267     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, depth);
2268
2269     /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2270     if( (physBitmap->pixmap_depth == 1) || (!X11DRV_XRender_Installed && physDev->depth == physBitmap->pixmap_depth) ||
2271         (src_format->format == dst_format->format) )
2272     {
2273         XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2274                    get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2275     }
2276     else /* We need depth conversion */
2277     {
2278         Picture src_pict, dst_pict;
2279         XRenderPictureAttributes pa;
2280         pa.subwindow_mode = IncludeInferiors;
2281         pa.repeat = RepeatNone;
2282
2283         src_pict = pXRenderCreatePicture(gdi_display, physBitmap->pixmap, src_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2284         dst_pict = pXRenderCreatePicture(gdi_display, physDev->brush.pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2285
2286         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, width, height);
2287         pXRenderFreePicture(gdi_display, src_pict);
2288         pXRenderFreePicture(gdi_display, dst_pict);
2289     }
2290     wine_tsx11_unlock();
2291 }
2292
2293 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2294                                       Pixmap pixmap, GC gc,
2295                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2296 {
2297     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2298     int width = dst->visrect.right - dst->visrect.left;
2299     int height = dst->visrect.bottom - dst->visrect.top;
2300     int x_src = physDevSrc->dc_rect.left + src->visrect.left;
2301     int y_src = physDevSrc->dc_rect.top + src->visrect.top;
2302     struct xrender_info *src_info = get_xrender_info(physDevSrc);
2303     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDevDst->depth, physDevDst->color_shifts);
2304     Picture src_pict=0, dst_pict=0, mask_pict=0;
2305     BOOL use_repeat;
2306     double xscale, yscale;
2307
2308     XRenderPictureAttributes pa;
2309     pa.subwindow_mode = IncludeInferiors;
2310     pa.repeat = RepeatNone;
2311
2312     TRACE("src depth=%d widthSrc=%d heightSrc=%d xSrc=%d ySrc=%d\n",
2313           physDevSrc->depth, src->width, src->height, x_src, y_src);
2314     TRACE("dst depth=%d widthDst=%d heightDst=%d\n", physDevDst->depth, dst->width, dst->height);
2315
2316     if(!X11DRV_XRender_Installed)
2317     {
2318         TRACE("Not using XRender since it is not available or disabled\n");
2319         return FALSE;
2320     }
2321
2322     /* XRender can't handle palettes, so abort */
2323     if(X11DRV_PALETTE_XPixelToPalette)
2324         return FALSE;
2325
2326     /* XRender is of no use in this case */
2327     if((physDevDst->depth == 1) && (physDevSrc->depth > 1))
2328         return FALSE;
2329
2330     /* Just use traditional X copy when the formats match and we don't need stretching */
2331     if((src_info->format->format == dst_format->format) && !stretch)
2332     {
2333         TRACE("Source and destination depth match and no stretching needed falling back to XCopyArea\n");
2334         wine_tsx11_lock();
2335         XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc, x_src, y_src, width, height, 0, 0);
2336         wine_tsx11_unlock();
2337         return TRUE;
2338     }
2339
2340     use_repeat = use_source_repeat( physDevSrc );
2341     if (!use_repeat)
2342     {
2343         xscale = src->width / (double)dst->width;
2344         yscale = src->height / (double)dst->height;
2345     }
2346     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2347
2348     /* mono -> color */
2349     if(physDevSrc->depth == 1 && physDevDst->depth > 1)
2350     {
2351         XRenderColor col;
2352         get_xrender_color(dst_format, physDevDst->textPixel, &col);
2353
2354         /* We use the source drawable as a mask */
2355         mask_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2356
2357         /* Use backgroundPixel as the foreground color */
2358         EnterCriticalSection( &xrender_cs );
2359         src_pict = get_tile_pict(dst_format, physDevDst->backgroundPixel);
2360
2361         /* Create a destination picture and fill it with textPixel color as the background color */
2362         wine_tsx11_lock();
2363         dst_pict = pXRenderCreatePicture(gdi_display, pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2364         pXRenderFillRectangle(gdi_display, PictOpSrc, dst_pict, &col, 0, 0, width, height);
2365
2366         xrender_mono_blit(src_pict, mask_pict, dst_pict, x_src, y_src, xscale, yscale, width, height);
2367
2368         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2369         wine_tsx11_unlock();
2370         LeaveCriticalSection( &xrender_cs );
2371     }
2372     else /* color -> color (can be at different depths) or mono -> mono */
2373     {
2374         if (physDevDst->depth == 32 && physDevSrc->depth < 32) mask_pict = get_no_alpha_mask();
2375         src_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2376
2377         wine_tsx11_lock();
2378         dst_pict = pXRenderCreatePicture(gdi_display,
2379                                           pixmap, dst_format->pict_format,
2380                                           CPSubwindowMode|CPRepeat, &pa);
2381
2382         xrender_blit(PictOpSrc, src_pict, mask_pict, dst_pict,
2383                      x_src, y_src, 0, 0, xscale, yscale, width, height);
2384
2385         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2386         wine_tsx11_unlock();
2387     }
2388     return TRUE;
2389 }
2390
2391 #else /* SONAME_LIBXRENDER */
2392
2393 void X11DRV_XRender_Init(void)
2394 {
2395     TRACE("XRender support not compiled in.\n");
2396     return;
2397 }
2398
2399 void X11DRV_XRender_Finalize(void)
2400 {
2401 }
2402
2403 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
2404 {
2405   assert(0);
2406   return FALSE;
2407 }
2408
2409 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
2410 {
2411   assert(0);
2412   return;
2413 }
2414
2415 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
2416 {
2417     assert(0);
2418     return;
2419 }
2420
2421 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
2422                                 const RECT *lprect, LPCWSTR wstr, UINT count,
2423                                 const INT *lpDx )
2424 {
2425   assert(0);
2426   return FALSE;
2427 }
2428
2429 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
2430 {
2431   assert(0);
2432   return;
2433 }
2434
2435 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2436                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2437 {
2438   FIXME("not supported - XRENDER headers were missing at compile time\n");
2439   return FALSE;
2440 }
2441
2442 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2443 {
2444     wine_tsx11_lock();
2445     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, physBitmap->pixmap_depth);
2446
2447     XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2448                get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2449     wine_tsx11_unlock();
2450 }
2451
2452 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2453 {
2454     return FALSE;
2455 }
2456
2457 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2458                                       Pixmap pixmap, GC gc,
2459                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2460 {
2461     return FALSE;
2462 }
2463 #endif /* SONAME_LIBXRENDER */