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