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