dmloader: Simplify the module refcount handling.
[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 = CreateRectRgnIndirect( lprect );
1870         saved_region = add_extra_clipping_region( physDev, clip_region );
1871         DeleteObject( clip_region );
1872     }
1873
1874     EnterCriticalSection(&xrender_cs);
1875
1876     entry = glyphsetCache + physDev->xrender->cache_index;
1877     if( disable_antialias == FALSE )
1878         aa_type = entry->aa_default;
1879     formatEntry = entry->format[aa_type];
1880
1881     for(idx = 0; idx < count; idx++) {
1882         if( !formatEntry ) {
1883             UploadGlyph(physDev, wstr[idx], aa_type);
1884             /* re-evaluate antialias since aa_default may have changed */
1885             if( disable_antialias == FALSE )
1886                 aa_type = entry->aa_default;
1887             formatEntry = entry->format[aa_type];
1888         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1889             UploadGlyph(physDev, wstr[idx], aa_type);
1890         }
1891     }
1892     if (!formatEntry)
1893     {
1894         WARN("could not upload requested glyphs\n");
1895         LeaveCriticalSection(&xrender_cs);
1896         goto done_unlock;
1897     }
1898
1899     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1900           physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1901
1902     if(X11DRV_XRender_Installed)
1903     {
1904         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1905         POINT offset = {0, 0};
1906         POINT desired, current;
1907         int render_op = PictOpOver;
1908         Picture pict = get_xrender_picture(physDev);
1909
1910         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1911            So we pass zeros to the function and move to our starting position using the first
1912            element of the elts array. */
1913
1914         desired.x = physDev->dc_rect.left + x;
1915         desired.y = physDev->dc_rect.top + y;
1916         current.x = current.y = 0;
1917
1918         tile_pict = get_tile_pict(dst_format, physDev->textPixel);
1919
1920         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1921          */
1922         if((dst_format->format == WXR_FORMAT_MONO) && (textPixel == 0))
1923             render_op = PictOpOutReverse; /* This gives us 'black' text */
1924
1925         for(idx = 0; idx < count; idx++)
1926         {
1927             elts[idx].glyphset = formatEntry->glyphset;
1928             elts[idx].chars = wstr + idx;
1929             elts[idx].nchars = 1;
1930             elts[idx].xOff = desired.x - current.x;
1931             elts[idx].yOff = desired.y - current.y;
1932
1933             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1934             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1935
1936             if(!lpDx)
1937             {
1938                 desired.x += formatEntry->gis[wstr[idx]].xOff;
1939                 desired.y += formatEntry->gis[wstr[idx]].yOff;
1940             }
1941             else
1942             {
1943                 if(flags & ETO_PDY)
1944                 {
1945                     offset.x += lpDx[idx * 2];
1946                     offset.y += lpDx[idx * 2 + 1];
1947                 }
1948                 else
1949                     offset.x += lpDx[idx];
1950                 desired.x = physDev->dc_rect.left + x + offset.x;
1951                 desired.y = physDev->dc_rect.top  + y + offset.y;
1952             }
1953         }
1954         wine_tsx11_lock();
1955         /* Make sure we don't have any transforms set from a previous call */
1956         set_xrender_transformation(pict, 1, 1, 0, 0);
1957         pXRenderCompositeText16(gdi_display, render_op,
1958                                 tile_pict,
1959                                 pict,
1960                                 formatEntry->font_format->pict_format,
1961                                 0, 0, 0, 0, elts, count);
1962         wine_tsx11_unlock();
1963         HeapFree(GetProcessHeap(), 0, elts);
1964     } else {
1965         POINT offset = {0, 0};
1966         wine_tsx11_lock();
1967         XSetForeground( gdi_display, physDev->gc, textPixel );
1968
1969         if(aa_type == AA_None || physDev->depth == 1)
1970         {
1971             void (* sharp_glyph_fn)(X11DRV_PDEVICE *, INT, INT, void *, XGlyphInfo *);
1972
1973             if(aa_type == AA_None)
1974                 sharp_glyph_fn = SharpGlyphMono;
1975             else
1976                 sharp_glyph_fn = SharpGlyphGray;
1977
1978             for(idx = 0; idx < count; idx++) {
1979                 sharp_glyph_fn(physDev,
1980                                physDev->dc_rect.left + x + offset.x,
1981                                physDev->dc_rect.top  + y + offset.y,
1982                                formatEntry->bitmaps[wstr[idx]],
1983                                &formatEntry->gis[wstr[idx]]);
1984                 if(lpDx)
1985                 {
1986                     if(flags & ETO_PDY)
1987                     {
1988                         offset.x += lpDx[idx * 2];
1989                         offset.y += lpDx[idx * 2 + 1];
1990                     }
1991                     else
1992                         offset.x += lpDx[idx];
1993                 }
1994                 else
1995                 {
1996                     offset.x += formatEntry->gis[wstr[idx]].xOff;
1997                     offset.y += formatEntry->gis[wstr[idx]].yOff;
1998                 }
1999             }
2000         } else {
2001             XImage *image;
2002             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
2003             RECT extents = {0, 0, 0, 0};
2004             POINT cur = {0, 0};
2005             int w = physDev->drawable_rect.right - physDev->drawable_rect.left;
2006             int h = physDev->drawable_rect.bottom - physDev->drawable_rect.top;
2007
2008             TRACE("drawable %dx%d\n", w, h);
2009
2010             for(idx = 0; idx < count; idx++) {
2011                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
2012                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
2013                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
2014                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
2015                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
2016                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
2017                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
2018                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
2019
2020                 if(lpDx)
2021                 {
2022                     if(flags & ETO_PDY)
2023                     {
2024                         cur.x += lpDx[idx * 2];
2025                         cur.y += lpDx[idx * 2 + 1];
2026                     }
2027                     else
2028                         cur.x += lpDx[idx];
2029                 }
2030                 else
2031                 {
2032                     cur.x += formatEntry->gis[wstr[idx]].xOff;
2033                     cur.y += formatEntry->gis[wstr[idx]].yOff;
2034                 }
2035             }
2036             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
2037                   extents.right, extents.bottom, physDev->dc_rect.left + x, physDev->dc_rect.top + y);
2038
2039             if(physDev->dc_rect.left + x + extents.left >= 0) {
2040                 image_x = physDev->dc_rect.left + x + extents.left;
2041                 image_off_x = 0;
2042             } else {
2043                 image_x = 0;
2044                 image_off_x = physDev->dc_rect.left + x + extents.left;
2045             }
2046             if(physDev->dc_rect.top + y + extents.top >= 0) {
2047                 image_y = physDev->dc_rect.top + y + extents.top;
2048                 image_off_y = 0;
2049             } else {
2050                 image_y = 0;
2051                 image_off_y = physDev->dc_rect.top + y + extents.top;
2052             }
2053             if(physDev->dc_rect.left + x + extents.right < w)
2054                 image_w = physDev->dc_rect.left + x + extents.right - image_x;
2055             else
2056                 image_w = w - image_x;
2057             if(physDev->dc_rect.top + y + extents.bottom < h)
2058                 image_h = physDev->dc_rect.top + y + extents.bottom - image_y;
2059             else
2060                 image_h = h - image_y;
2061
2062             if(image_w <= 0 || image_h <= 0) goto no_image;
2063
2064             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2065             image = XGetImage(gdi_display, physDev->drawable,
2066                               image_x, image_y, image_w, image_h,
2067                               AllPlanes, ZPixmap);
2068             X11DRV_check_error();
2069
2070             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2071                   gdi_display, (int)physDev->drawable, image_x, image_y,
2072                   image_w, image_h, AllPlanes, ZPixmap,
2073                   physDev->depth, image);
2074             if(!image) {
2075                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
2076                                            physDev->depth);
2077                 GC gc;
2078                 XGCValues gcv;
2079
2080                 gcv.graphics_exposures = False;
2081                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
2082                 XCopyArea(gdi_display, physDev->drawable, xpm, gc, image_x, image_y,
2083                           image_w, image_h, 0, 0);
2084                 XFreeGC(gdi_display, gc);
2085                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2086                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
2087                                   ZPixmap);
2088                 X11DRV_check_error();
2089                 XFreePixmap(gdi_display, xpm);
2090             }
2091             if(!image) goto no_image;
2092
2093             image->red_mask = visual->red_mask;
2094             image->green_mask = visual->green_mask;
2095             image->blue_mask = visual->blue_mask;
2096
2097             for(idx = 0; idx < count; idx++) {
2098                 SmoothGlyphGray(image,
2099                                 offset.x + image_off_x - extents.left,
2100                                 offset.y + image_off_y - extents.top,
2101                                 formatEntry->bitmaps[wstr[idx]],
2102                                 &formatEntry->gis[wstr[idx]],
2103                                 physDev->textPixel);
2104                 if(lpDx)
2105                 {
2106                     if(flags & ETO_PDY)
2107                     {
2108                         offset.x += lpDx[idx * 2];
2109                         offset.y += lpDx[idx * 2 + 1];
2110                     }
2111                     else
2112                         offset.x += lpDx[idx];
2113                 }
2114                 else
2115                 {
2116                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2117                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2118                 }
2119             }
2120             XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
2121                       image_x, image_y, image_w, image_h);
2122             XDestroyImage(image);
2123         }
2124     no_image:
2125         wine_tsx11_unlock();
2126     }
2127     LeaveCriticalSection(&xrender_cs);
2128
2129     if (saved_region) restore_clipping_region( physDev, saved_region );
2130
2131     retv = TRUE;
2132
2133 done_unlock:
2134     X11DRV_UnlockDIBSection( physDev, TRUE );
2135     return retv;
2136 }
2137
2138 /* Helper function for (stretched) blitting using xrender */
2139 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
2140                           int x_src, int y_src, int x_dst, int y_dst,
2141                           double xscale, double yscale, int width, int height )
2142 {
2143     int x_offset, y_offset;
2144
2145     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2146      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2147      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2148     if(xscale != 1.0 || yscale != 1.0)
2149     {
2150         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2151          * in the wrong quadrant of the x-y plane.
2152          */
2153         x_offset = (xscale < 0) ? -width : 0;
2154         y_offset = (yscale < 0) ? -height : 0;
2155         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2156     }
2157     else
2158     {
2159         x_offset = x_src;
2160         y_offset = y_src;
2161         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2162     }
2163     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
2164                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
2165 }
2166
2167 /* Helper function for (stretched) mono->color blitting using xrender */
2168 static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_pict,
2169                                int x_src, int y_src, double xscale, double yscale, int width, int height )
2170 {
2171     int x_offset, y_offset;
2172
2173     /* When doing a mono->color blit, 'src_pict' contains a 1x1 picture for tiling, the actual
2174      * source data is in mask_pict.  The 'src_pict' data effectively acts as an alpha channel to the
2175      * tile data. We need PictOpOver for correct rendering.
2176      * Note since the 'source data' is in the mask picture, we have to pass x_src / y_src using
2177      * mask_x / mask_y
2178      */
2179     if (xscale != 1.0 || yscale != 1.0)
2180     {
2181         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2182          * in the wrong quadrant of the x-y plane.
2183          */
2184         x_offset = (xscale < 0) ? -width : 0;
2185         y_offset = (yscale < 0) ? -height : 0;
2186         set_xrender_transformation(mask_pict, xscale, yscale, x_src, y_src);
2187     }
2188     else
2189     {
2190         x_offset = x_src;
2191         y_offset = y_src;
2192         set_xrender_transformation(mask_pict, 1, 1, 0, 0);
2193     }
2194     pXRenderComposite(gdi_display, PictOpOver, src_pict, mask_pict, dst_pict,
2195                       0, 0, x_offset, y_offset, 0, 0, width, height);
2196 }
2197
2198 /******************************************************************************
2199  * AlphaBlend
2200  */
2201 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, struct bitblt_coords *dst,
2202                          X11DRV_PDEVICE *devSrc, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2203 {
2204     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2205     struct xrender_info *src_info = get_xrender_info( devSrc );
2206     double xscale, yscale;
2207     BOOL use_repeat;
2208
2209     if(!X11DRV_XRender_Installed) {
2210         FIXME("Unable to AlphaBlend without Xrender\n");
2211         return FALSE;
2212     }
2213
2214     if (devSrc != devDst) X11DRV_LockDIBSection( devSrc, DIB_Status_GdiMod );
2215     X11DRV_LockDIBSection( devDst, DIB_Status_GdiMod );
2216
2217     dst_pict = get_xrender_picture( devDst );
2218
2219     use_repeat = use_source_repeat( devSrc );
2220     if (!use_repeat)
2221     {
2222         xscale = src->width / (double)dst->width;
2223         yscale = src->height / (double)dst->height;
2224     }
2225     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2226
2227     if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && src_info->format)
2228     {
2229         /* we need a source picture with no alpha */
2230         WXRFormat format = get_format_without_alpha( src_info->format->format );
2231         if (format != src_info->format->format)
2232         {
2233             XRenderPictureAttributes pa;
2234             const WineXRenderFormat *fmt = get_xrender_format( format );
2235
2236             wine_tsx11_lock();
2237             pa.subwindow_mode = IncludeInferiors;
2238             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2239             tmp_pict = pXRenderCreatePicture( gdi_display, devSrc->drawable, fmt->pict_format,
2240                                               CPSubwindowMode|CPRepeat, &pa );
2241             wine_tsx11_unlock();
2242             src_pict = tmp_pict;
2243         }
2244     }
2245
2246     if (!src_pict) src_pict = get_xrender_picture_source( devSrc, use_repeat );
2247
2248     EnterCriticalSection( &xrender_cs );
2249     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2250
2251     wine_tsx11_lock();
2252     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2253                   devSrc->dc_rect.left + src->visrect.left, devSrc->dc_rect.top + src->visrect.top,
2254                   devDst->dc_rect.left + dst->visrect.left, devDst->dc_rect.top + dst->visrect.top,
2255                   xscale, yscale,
2256                   dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top );
2257     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2258     wine_tsx11_unlock();
2259
2260     LeaveCriticalSection( &xrender_cs );
2261     if (devSrc != devDst) X11DRV_UnlockDIBSection( devSrc, FALSE );
2262     X11DRV_UnlockDIBSection( devDst, TRUE );
2263     return TRUE;
2264 }
2265
2266
2267 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2268 {
2269     /* 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 */
2270     int depth = physBitmap->pixmap_depth == 1 ? 1 : physDev->depth;
2271     const WineXRenderFormat *src_format = get_xrender_format_from_color_shifts(physBitmap->pixmap_depth, &physBitmap->pixmap_color_shifts);
2272     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
2273
2274     wine_tsx11_lock();
2275     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, depth);
2276
2277     /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2278     if( (physBitmap->pixmap_depth == 1) || (!X11DRV_XRender_Installed && physDev->depth == physBitmap->pixmap_depth) ||
2279         (src_format->format == dst_format->format) )
2280     {
2281         XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2282                    get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2283     }
2284     else /* We need depth conversion */
2285     {
2286         Picture src_pict, dst_pict;
2287         XRenderPictureAttributes pa;
2288         pa.subwindow_mode = IncludeInferiors;
2289         pa.repeat = RepeatNone;
2290
2291         src_pict = pXRenderCreatePicture(gdi_display, physBitmap->pixmap, src_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2292         dst_pict = pXRenderCreatePicture(gdi_display, physDev->brush.pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2293
2294         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, width, height);
2295         pXRenderFreePicture(gdi_display, src_pict);
2296         pXRenderFreePicture(gdi_display, dst_pict);
2297     }
2298     wine_tsx11_unlock();
2299 }
2300
2301 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2302                                       Pixmap pixmap, GC gc,
2303                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2304 {
2305     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2306     int width = dst->visrect.right - dst->visrect.left;
2307     int height = dst->visrect.bottom - dst->visrect.top;
2308     int x_src = physDevSrc->dc_rect.left + src->visrect.left;
2309     int y_src = physDevSrc->dc_rect.top + src->visrect.top;
2310     struct xrender_info *src_info = get_xrender_info(physDevSrc);
2311     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDevDst->depth, physDevDst->color_shifts);
2312     Picture src_pict=0, dst_pict=0, mask_pict=0;
2313     BOOL use_repeat;
2314     double xscale, yscale;
2315
2316     XRenderPictureAttributes pa;
2317     pa.subwindow_mode = IncludeInferiors;
2318     pa.repeat = RepeatNone;
2319
2320     TRACE("src depth=%d widthSrc=%d heightSrc=%d xSrc=%d ySrc=%d\n",
2321           physDevSrc->depth, src->width, src->height, x_src, y_src);
2322     TRACE("dst depth=%d widthDst=%d heightDst=%d\n", physDevDst->depth, dst->width, dst->height);
2323
2324     if(!X11DRV_XRender_Installed)
2325     {
2326         TRACE("Not using XRender since it is not available or disabled\n");
2327         return FALSE;
2328     }
2329
2330     /* XRender can't handle palettes, so abort */
2331     if(X11DRV_PALETTE_XPixelToPalette)
2332         return FALSE;
2333
2334     /* XRender is of no use in this case */
2335     if((physDevDst->depth == 1) && (physDevSrc->depth > 1))
2336         return FALSE;
2337
2338     /* Just use traditional X copy when the formats match and we don't need stretching */
2339     if((src_info->format->format == dst_format->format) && !stretch)
2340     {
2341         TRACE("Source and destination depth match and no stretching needed falling back to XCopyArea\n");
2342         wine_tsx11_lock();
2343         XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc, x_src, y_src, width, height, 0, 0);
2344         wine_tsx11_unlock();
2345         return TRUE;
2346     }
2347
2348     use_repeat = use_source_repeat( physDevSrc );
2349     if (!use_repeat)
2350     {
2351         xscale = src->width / (double)dst->width;
2352         yscale = src->height / (double)dst->height;
2353     }
2354     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2355
2356     /* mono -> color */
2357     if(physDevSrc->depth == 1 && physDevDst->depth > 1)
2358     {
2359         XRenderColor col;
2360         get_xrender_color(dst_format, physDevDst->textPixel, &col);
2361
2362         /* We use the source drawable as a mask */
2363         mask_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2364
2365         /* Use backgroundPixel as the foreground color */
2366         EnterCriticalSection( &xrender_cs );
2367         src_pict = get_tile_pict(dst_format, physDevDst->backgroundPixel);
2368
2369         /* Create a destination picture and fill it with textPixel color as the background color */
2370         wine_tsx11_lock();
2371         dst_pict = pXRenderCreatePicture(gdi_display, pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2372         pXRenderFillRectangle(gdi_display, PictOpSrc, dst_pict, &col, 0, 0, width, height);
2373
2374         xrender_mono_blit(src_pict, mask_pict, dst_pict, x_src, y_src, xscale, yscale, width, height);
2375
2376         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2377         wine_tsx11_unlock();
2378         LeaveCriticalSection( &xrender_cs );
2379     }
2380     else /* color -> color (can be at different depths) or mono -> mono */
2381     {
2382         if (physDevDst->depth == 32 && physDevSrc->depth < 32) mask_pict = get_no_alpha_mask();
2383         src_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2384
2385         wine_tsx11_lock();
2386         dst_pict = pXRenderCreatePicture(gdi_display,
2387                                           pixmap, dst_format->pict_format,
2388                                           CPSubwindowMode|CPRepeat, &pa);
2389
2390         xrender_blit(PictOpSrc, src_pict, mask_pict, dst_pict,
2391                      x_src, y_src, 0, 0, xscale, yscale, width, height);
2392
2393         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2394         wine_tsx11_unlock();
2395     }
2396     return TRUE;
2397 }
2398
2399 #else /* SONAME_LIBXRENDER */
2400
2401 void X11DRV_XRender_Init(void)
2402 {
2403     TRACE("XRender support not compiled in.\n");
2404     return;
2405 }
2406
2407 void X11DRV_XRender_Finalize(void)
2408 {
2409 }
2410
2411 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
2412 {
2413   assert(0);
2414   return FALSE;
2415 }
2416
2417 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
2418 {
2419   assert(0);
2420   return;
2421 }
2422
2423 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
2424 {
2425     assert(0);
2426     return;
2427 }
2428
2429 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
2430                                 const RECT *lprect, LPCWSTR wstr, UINT count,
2431                                 const INT *lpDx )
2432 {
2433   assert(0);
2434   return FALSE;
2435 }
2436
2437 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
2438 {
2439   assert(0);
2440   return;
2441 }
2442
2443 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2444                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2445 {
2446   FIXME("not supported - XRENDER headers were missing at compile time\n");
2447   return FALSE;
2448 }
2449
2450 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2451 {
2452     wine_tsx11_lock();
2453     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, physBitmap->pixmap_depth);
2454
2455     XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2456                get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2457     wine_tsx11_unlock();
2458 }
2459
2460 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2461 {
2462     return FALSE;
2463 }
2464
2465 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2466                                       Pixmap pixmap, GC gc,
2467                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2468 {
2469     return FALSE;
2470 }
2471 #endif /* SONAME_LIBXRENDER */