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