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