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