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