d3d10: Add argument check to ID3D10Effect::GetTechniqueByName().
[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     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
1630     Picture tile_pict = 0;
1631
1632     /* Do we need to disable antialiasing because of palette mode? */
1633     if( !physDev->bitmap || GetObjectW( physDev->bitmap->hbitmap, sizeof(bmp), &bmp ) != sizeof(bmp) ) {
1634         TRACE("bitmap is not a DIB\n");
1635     }
1636     else if (bmp.dsBmih.biBitCount <= 8) {
1637         TRACE("Disabling antialiasing\n");
1638         disable_antialias = TRUE;
1639     }
1640
1641     xgcval.function = GXcopy;
1642     xgcval.background = physDev->backgroundPixel;
1643     xgcval.fill_style = FillSolid;
1644     wine_tsx11_lock();
1645     XChangeGC( gdi_display, physDev->gc, GCFunction | GCBackground | GCFillStyle, &xgcval );
1646     wine_tsx11_unlock();
1647
1648     X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1649
1650     if(physDev->depth == 1) {
1651         if((physDev->textPixel & 0xffffff) == 0) {
1652             textPixel = 0;
1653             backgroundPixel = 1;
1654         } else {
1655             textPixel = 1;
1656             backgroundPixel = 0;
1657         }
1658     } else {
1659         textPixel = physDev->textPixel;
1660         backgroundPixel = physDev->backgroundPixel;
1661     }
1662
1663     if(flags & ETO_OPAQUE)
1664     {
1665         wine_tsx11_lock();
1666         XSetForeground( gdi_display, physDev->gc, backgroundPixel );
1667         XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1668                         physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top,
1669                         lprect->right - lprect->left, lprect->bottom - lprect->top );
1670         wine_tsx11_unlock();
1671     }
1672
1673     if(count == 0)
1674     {
1675         retv = TRUE;
1676         goto done_unlock;
1677     }
1678
1679     if (flags & ETO_CLIPPED)
1680     {
1681         HRGN clip_region;
1682
1683         clip_region = CreateRectRgnIndirect( lprect );
1684         /* make a copy of the current device region */
1685         saved_region = CreateRectRgn( 0, 0, 0, 0 );
1686         CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
1687         X11DRV_SetDeviceClipping( physDev, saved_region, clip_region );
1688         DeleteObject( clip_region );
1689     }
1690
1691     EnterCriticalSection(&xrender_cs);
1692
1693     entry = glyphsetCache + physDev->xrender->cache_index;
1694     if( disable_antialias == FALSE )
1695         aa_type = entry->aa_default;
1696     formatEntry = entry->format[aa_type];
1697
1698     for(idx = 0; idx < count; idx++) {
1699         if( !formatEntry ) {
1700             UploadGlyph(physDev, wstr[idx], aa_type);
1701             /* re-evaluate antialias since aa_default may have changed */
1702             if( disable_antialias == FALSE )
1703                 aa_type = entry->aa_default;
1704             formatEntry = entry->format[aa_type];
1705         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1706             UploadGlyph(physDev, wstr[idx], aa_type);
1707         }
1708     }
1709     if (!formatEntry)
1710     {
1711         WARN("could not upload requested glyphs\n");
1712         LeaveCriticalSection(&xrender_cs);
1713         goto done_unlock;
1714     }
1715
1716     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1717           physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1718
1719     if(X11DRV_XRender_Installed)
1720     {
1721         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1722         POINT offset = {0, 0};
1723         POINT desired, current;
1724         int render_op = PictOpOver;
1725         Picture pict = get_xrender_picture(physDev);
1726
1727         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1728            So we pass zeros to the function and move to our starting position using the first
1729            element of the elts array. */
1730
1731         desired.x = physDev->dc_rect.left + x;
1732         desired.y = physDev->dc_rect.top + y;
1733         current.x = current.y = 0;
1734
1735         tile_pict = get_tile_pict(dst_format, physDev->textPixel);
1736
1737         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1738          */
1739         if((dst_format->format == WXR_FORMAT_MONO) && (textPixel == 0))
1740             render_op = PictOpOutReverse; /* This gives us 'black' text */
1741
1742         for(idx = 0; idx < count; idx++)
1743         {
1744             elts[idx].glyphset = formatEntry->glyphset;
1745             elts[idx].chars = wstr + idx;
1746             elts[idx].nchars = 1;
1747             elts[idx].xOff = desired.x - current.x;
1748             elts[idx].yOff = desired.y - current.y;
1749
1750             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1751             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1752
1753             if(!lpDx)
1754             {
1755                 desired.x += formatEntry->gis[wstr[idx]].xOff;
1756                 desired.y += formatEntry->gis[wstr[idx]].yOff;
1757             }
1758             else
1759             {
1760                 if(flags & ETO_PDY)
1761                 {
1762                     offset.x += lpDx[idx * 2];
1763                     offset.y += lpDx[idx * 2 + 1];
1764                 }
1765                 else
1766                     offset.x += lpDx[idx];
1767                 desired.x = physDev->dc_rect.left + x + offset.x;
1768                 desired.y = physDev->dc_rect.top  + y + offset.y;
1769             }
1770         }
1771         wine_tsx11_lock();
1772         /* Make sure we don't have any transforms set from a previous call */
1773         set_xrender_transformation(pict, 1, 1, 0, 0);
1774         pXRenderCompositeText16(gdi_display, render_op,
1775                                 tile_pict,
1776                                 pict,
1777                                 formatEntry->font_format->pict_format,
1778                                 0, 0, 0, 0, elts, count);
1779         wine_tsx11_unlock();
1780         HeapFree(GetProcessHeap(), 0, elts);
1781     } else {
1782         POINT offset = {0, 0};
1783         wine_tsx11_lock();
1784         XSetForeground( gdi_display, physDev->gc, textPixel );
1785
1786         if(aa_type == AA_None || physDev->depth == 1)
1787         {
1788             void (* sharp_glyph_fn)(X11DRV_PDEVICE *, INT, INT, void *, XGlyphInfo *);
1789
1790             if(aa_type == AA_None)
1791                 sharp_glyph_fn = SharpGlyphMono;
1792             else
1793                 sharp_glyph_fn = SharpGlyphGray;
1794
1795             for(idx = 0; idx < count; idx++) {
1796                 sharp_glyph_fn(physDev,
1797                                physDev->dc_rect.left + x + offset.x,
1798                                physDev->dc_rect.top  + y + offset.y,
1799                                formatEntry->bitmaps[wstr[idx]],
1800                                &formatEntry->gis[wstr[idx]]);
1801                 if(lpDx)
1802                 {
1803                     if(flags & ETO_PDY)
1804                     {
1805                         offset.x += lpDx[idx * 2];
1806                         offset.y += lpDx[idx * 2 + 1];
1807                     }
1808                     else
1809                         offset.x += lpDx[idx];
1810                 }
1811                 else
1812                 {
1813                     offset.x += formatEntry->gis[wstr[idx]].xOff;
1814                     offset.y += formatEntry->gis[wstr[idx]].yOff;
1815                 }
1816             }
1817         } else {
1818             XImage *image;
1819             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
1820             RECT extents = {0, 0, 0, 0};
1821             POINT cur = {0, 0};
1822             int w = physDev->drawable_rect.right - physDev->drawable_rect.left;
1823             int h = physDev->drawable_rect.bottom - physDev->drawable_rect.top;
1824
1825             TRACE("drawable %dx%d\n", w, h);
1826
1827             for(idx = 0; idx < count; idx++) {
1828                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
1829                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
1830                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
1831                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
1832                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
1833                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
1834                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
1835                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
1836
1837                 if(lpDx)
1838                 {
1839                     if(flags & ETO_PDY)
1840                     {
1841                         cur.x += lpDx[idx * 2];
1842                         cur.y += lpDx[idx * 2 + 1];
1843                     }
1844                     else
1845                         cur.x += lpDx[idx];
1846                 }
1847                 else
1848                 {
1849                     cur.x += formatEntry->gis[wstr[idx]].xOff;
1850                     cur.y += formatEntry->gis[wstr[idx]].yOff;
1851                 }
1852             }
1853             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
1854                   extents.right, extents.bottom, physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1855
1856             if(physDev->dc_rect.left + x + extents.left >= 0) {
1857                 image_x = physDev->dc_rect.left + x + extents.left;
1858                 image_off_x = 0;
1859             } else {
1860                 image_x = 0;
1861                 image_off_x = physDev->dc_rect.left + x + extents.left;
1862             }
1863             if(physDev->dc_rect.top + y + extents.top >= 0) {
1864                 image_y = physDev->dc_rect.top + y + extents.top;
1865                 image_off_y = 0;
1866             } else {
1867                 image_y = 0;
1868                 image_off_y = physDev->dc_rect.top + y + extents.top;
1869             }
1870             if(physDev->dc_rect.left + x + extents.right < w)
1871                 image_w = physDev->dc_rect.left + x + extents.right - image_x;
1872             else
1873                 image_w = w - image_x;
1874             if(physDev->dc_rect.top + y + extents.bottom < h)
1875                 image_h = physDev->dc_rect.top + y + extents.bottom - image_y;
1876             else
1877                 image_h = h - image_y;
1878
1879             if(image_w <= 0 || image_h <= 0) goto no_image;
1880
1881             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
1882             image = XGetImage(gdi_display, physDev->drawable,
1883                               image_x, image_y, image_w, image_h,
1884                               AllPlanes, ZPixmap);
1885             X11DRV_check_error();
1886
1887             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
1888                   gdi_display, (int)physDev->drawable, image_x, image_y,
1889                   image_w, image_h, AllPlanes, ZPixmap,
1890                   physDev->depth, image);
1891             if(!image) {
1892                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
1893                                            physDev->depth);
1894                 GC gc;
1895                 XGCValues gcv;
1896
1897                 gcv.graphics_exposures = False;
1898                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
1899                 XCopyArea(gdi_display, physDev->drawable, xpm, gc, image_x, image_y,
1900                           image_w, image_h, 0, 0);
1901                 XFreeGC(gdi_display, gc);
1902                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
1903                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
1904                                   ZPixmap);
1905                 X11DRV_check_error();
1906                 XFreePixmap(gdi_display, xpm);
1907             }
1908             if(!image) goto no_image;
1909
1910             image->red_mask = visual->red_mask;
1911             image->green_mask = visual->green_mask;
1912             image->blue_mask = visual->blue_mask;
1913
1914             for(idx = 0; idx < count; idx++) {
1915                 SmoothGlyphGray(image,
1916                                 offset.x + image_off_x - extents.left,
1917                                 offset.y + image_off_y - extents.top,
1918                                 formatEntry->bitmaps[wstr[idx]],
1919                                 &formatEntry->gis[wstr[idx]],
1920                                 physDev->textPixel);
1921                 if(lpDx)
1922                 {
1923                     if(flags & ETO_PDY)
1924                     {
1925                         offset.x += lpDx[idx * 2];
1926                         offset.y += lpDx[idx * 2 + 1];
1927                     }
1928                     else
1929                         offset.x += lpDx[idx];
1930                 }
1931                 else
1932                 {
1933                     offset.x += formatEntry->gis[wstr[idx]].xOff;
1934                     offset.y += formatEntry->gis[wstr[idx]].yOff;
1935                 }
1936             }
1937             XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
1938                       image_x, image_y, image_w, image_h);
1939             XDestroyImage(image);
1940         }
1941     no_image:
1942         wine_tsx11_unlock();
1943     }
1944     LeaveCriticalSection(&xrender_cs);
1945
1946     if (flags & ETO_CLIPPED)
1947     {
1948         /* restore the device region */
1949         X11DRV_SetDeviceClipping( physDev, saved_region, 0 );
1950         DeleteObject( saved_region );
1951     }
1952
1953     retv = TRUE;
1954
1955 done_unlock:
1956     X11DRV_UnlockDIBSection( physDev, TRUE );
1957     return retv;
1958 }
1959
1960 /* Helper function for (stretched) blitting using xrender */
1961 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
1962                           int x_src, int y_src, int x_dst, int y_dst,
1963                           double xscale, double yscale, int width, int height )
1964 {
1965     int x_offset, y_offset;
1966
1967     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
1968      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
1969      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
1970     if(xscale != 1.0 || yscale != 1.0)
1971     {
1972         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1973          * in the wrong quadrant of the x-y plane.
1974          */
1975         x_offset = (xscale < 0) ? -width : 0;
1976         y_offset = (yscale < 0) ? -height : 0;
1977         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1978     }
1979     else
1980     {
1981         x_offset = x_src;
1982         y_offset = y_src;
1983         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1984     }
1985     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
1986                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
1987 }
1988
1989 /* Helper function for (stretched) mono->color blitting using xrender */
1990 static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_pict,
1991                                int x_src, int y_src, double xscale, double yscale, int width, int height )
1992 {
1993     int x_offset, y_offset;
1994
1995     /* When doing a mono->color blit, 'src_pict' contains a 1x1 picture for tiling, the actual
1996      * source data is in mask_pict.  The 'src_pict' data effectively acts as an alpha channel to the
1997      * tile data. We need PictOpOver for correct rendering.
1998      * Note since the 'source data' is in the mask picture, we have to pass x_src / y_src using
1999      * mask_x / mask_y
2000      */
2001     if (xscale != 1.0 || yscale != 1.0)
2002     {
2003         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2004          * in the wrong quadrant of the x-y plane.
2005          */
2006         x_offset = (xscale < 0) ? -width : 0;
2007         y_offset = (yscale < 0) ? -height : 0;
2008         set_xrender_transformation(mask_pict, xscale, yscale, x_src, y_src);
2009     }
2010     else
2011     {
2012         x_offset = x_src;
2013         y_offset = y_src;
2014         set_xrender_transformation(mask_pict, 1, 1, 0, 0);
2015     }
2016     pXRenderComposite(gdi_display, PictOpOver, src_pict, mask_pict, dst_pict,
2017                       0, 0, x_offset, y_offset, 0, 0, width, height);
2018 }
2019
2020 /******************************************************************************
2021  * AlphaBlend
2022  */
2023 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2024                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2025 {
2026     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2027     struct xrender_info *src_info = get_xrender_info( devSrc );
2028     double xscale, yscale;
2029     BOOL use_repeat;
2030
2031     if(!X11DRV_XRender_Installed) {
2032         FIXME("Unable to AlphaBlend without Xrender\n");
2033         return FALSE;
2034     }
2035
2036     if (devSrc != devDst) X11DRV_LockDIBSection( devSrc, DIB_Status_GdiMod );
2037     X11DRV_LockDIBSection( devDst, DIB_Status_GdiMod );
2038
2039     dst_pict = get_xrender_picture( devDst );
2040
2041     use_repeat = use_source_repeat( devSrc );
2042     if (!use_repeat)
2043     {
2044         xscale = src->width / (double)dst->width;
2045         yscale = src->height / (double)dst->height;
2046     }
2047     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2048
2049     if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && src_info->format)
2050     {
2051         /* we need a source picture with no alpha */
2052         WXRFormat format = get_format_without_alpha( src_info->format->format );
2053         if (format != src_info->format->format)
2054         {
2055             XRenderPictureAttributes pa;
2056             const WineXRenderFormat *fmt = get_xrender_format( format );
2057
2058             wine_tsx11_lock();
2059             pa.subwindow_mode = IncludeInferiors;
2060             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2061             tmp_pict = pXRenderCreatePicture( gdi_display, devSrc->drawable, fmt->pict_format,
2062                                               CPSubwindowMode|CPRepeat, &pa );
2063             wine_tsx11_unlock();
2064             src_pict = tmp_pict;
2065         }
2066     }
2067
2068     if (!src_pict) src_pict = get_xrender_picture_source( devSrc, use_repeat );
2069
2070     EnterCriticalSection( &xrender_cs );
2071     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2072
2073     wine_tsx11_lock();
2074     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2075                   devSrc->dc_rect.left + src->visrect.left, devSrc->dc_rect.top + src->visrect.top,
2076                   devDst->dc_rect.left + dst->visrect.left, devDst->dc_rect.top + dst->visrect.top,
2077                   xscale, yscale,
2078                   dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top );
2079     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2080     wine_tsx11_unlock();
2081
2082     LeaveCriticalSection( &xrender_cs );
2083     if (devSrc != devDst) X11DRV_UnlockDIBSection( devSrc, FALSE );
2084     X11DRV_UnlockDIBSection( devDst, TRUE );
2085     return TRUE;
2086 }
2087
2088
2089 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2090 {
2091     /* 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 */
2092     int depth = physBitmap->pixmap_depth == 1 ? 1 : physDev->depth;
2093     const WineXRenderFormat *src_format = get_xrender_format_from_color_shifts(physBitmap->pixmap_depth, &physBitmap->pixmap_color_shifts);
2094     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
2095
2096     wine_tsx11_lock();
2097     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, depth);
2098
2099     /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2100     if( (physBitmap->pixmap_depth == 1) || (!X11DRV_XRender_Installed && physDev->depth == physBitmap->pixmap_depth) ||
2101         (src_format->format == dst_format->format) )
2102     {
2103         XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2104                    get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2105     }
2106     else /* We need depth conversion */
2107     {
2108         Picture src_pict, dst_pict;
2109         XRenderPictureAttributes pa;
2110         pa.subwindow_mode = IncludeInferiors;
2111         pa.repeat = RepeatNone;
2112
2113         src_pict = pXRenderCreatePicture(gdi_display, physBitmap->pixmap, src_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2114         dst_pict = pXRenderCreatePicture(gdi_display, physDev->brush.pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2115
2116         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, width, height);
2117         pXRenderFreePicture(gdi_display, src_pict);
2118         pXRenderFreePicture(gdi_display, dst_pict);
2119     }
2120     wine_tsx11_unlock();
2121 }
2122
2123 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2124                                       Pixmap pixmap, GC gc,
2125                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2126 {
2127     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2128     int width = dst->visrect.right - dst->visrect.left;
2129     int height = dst->visrect.bottom - dst->visrect.top;
2130     int x_src = physDevSrc->dc_rect.left + src->visrect.left;
2131     int y_src = physDevSrc->dc_rect.top + src->visrect.top;
2132     struct xrender_info *src_info = get_xrender_info(physDevSrc);
2133     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDevDst->depth, physDevDst->color_shifts);
2134     Picture src_pict=0, dst_pict=0, mask_pict=0;
2135     BOOL use_repeat;
2136     double xscale, yscale;
2137
2138     XRenderPictureAttributes pa;
2139     pa.subwindow_mode = IncludeInferiors;
2140     pa.repeat = RepeatNone;
2141
2142     TRACE("src depth=%d widthSrc=%d heightSrc=%d xSrc=%d ySrc=%d\n",
2143           physDevSrc->depth, src->width, src->height, x_src, y_src);
2144     TRACE("dst depth=%d widthDst=%d heightDst=%d\n", physDevDst->depth, dst->width, dst->height);
2145
2146     if(!X11DRV_XRender_Installed)
2147     {
2148         TRACE("Not using XRender since it is not available or disabled\n");
2149         return FALSE;
2150     }
2151
2152     /* XRender can't handle palettes, so abort */
2153     if(X11DRV_PALETTE_XPixelToPalette)
2154         return FALSE;
2155
2156     /* XRender is of no use in this case */
2157     if((physDevDst->depth == 1) && (physDevSrc->depth > 1))
2158         return FALSE;
2159
2160     /* Just use traditional X copy when the formats match and we don't need stretching */
2161     if((src_info->format->format == dst_format->format) && !stretch)
2162     {
2163         TRACE("Source and destination depth match and no stretching needed falling back to XCopyArea\n");
2164         wine_tsx11_lock();
2165         XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc, x_src, y_src, width, height, 0, 0);
2166         wine_tsx11_unlock();
2167         return TRUE;
2168     }
2169
2170     use_repeat = use_source_repeat( physDevSrc );
2171     if (!use_repeat)
2172     {
2173         xscale = src->width / (double)dst->width;
2174         yscale = src->height / (double)dst->height;
2175     }
2176     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2177
2178     /* mono -> color */
2179     if(physDevSrc->depth == 1 && physDevDst->depth > 1)
2180     {
2181         XRenderColor col;
2182         get_xrender_color(dst_format, physDevDst->textPixel, &col);
2183
2184         /* We use the source drawable as a mask */
2185         mask_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2186
2187         /* Use backgroundPixel as the foreground color */
2188         EnterCriticalSection( &xrender_cs );
2189         src_pict = get_tile_pict(dst_format, physDevDst->backgroundPixel);
2190
2191         /* Create a destination picture and fill it with textPixel color as the background color */
2192         wine_tsx11_lock();
2193         dst_pict = pXRenderCreatePicture(gdi_display, pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2194         pXRenderFillRectangle(gdi_display, PictOpSrc, dst_pict, &col, 0, 0, width, height);
2195
2196         xrender_mono_blit(src_pict, mask_pict, dst_pict, x_src, y_src, xscale, yscale, width, height);
2197
2198         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2199         wine_tsx11_unlock();
2200         LeaveCriticalSection( &xrender_cs );
2201     }
2202     else /* color -> color (can be at different depths) or mono -> mono */
2203     {
2204         src_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2205
2206         wine_tsx11_lock();
2207         dst_pict = pXRenderCreatePicture(gdi_display,
2208                                           pixmap, dst_format->pict_format,
2209                                           CPSubwindowMode|CPRepeat, &pa);
2210
2211         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, x_src, y_src, 0, 0, xscale, yscale, width, height);
2212
2213         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2214         wine_tsx11_unlock();
2215     }
2216     return TRUE;
2217 }
2218
2219 #else /* SONAME_LIBXRENDER */
2220
2221 void X11DRV_XRender_Init(void)
2222 {
2223     TRACE("XRender support not compiled in.\n");
2224     return;
2225 }
2226
2227 void X11DRV_XRender_Finalize(void)
2228 {
2229 }
2230
2231 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
2232 {
2233   assert(0);
2234   return FALSE;
2235 }
2236
2237 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
2238 {
2239   assert(0);
2240   return;
2241 }
2242
2243 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
2244 {
2245     assert(0);
2246     return;
2247 }
2248
2249 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
2250                                 const RECT *lprect, LPCWSTR wstr, UINT count,
2251                                 const INT *lpDx )
2252 {
2253   assert(0);
2254   return FALSE;
2255 }
2256
2257 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
2258 {
2259   assert(0);
2260   return;
2261 }
2262
2263 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2264                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2265 {
2266   FIXME("not supported - XRENDER headers were missing at compile time\n");
2267   return FALSE;
2268 }
2269
2270 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2271 {
2272     wine_tsx11_lock();
2273     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, physBitmap->pixmap_depth);
2274
2275     XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2276                get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2277     wine_tsx11_unlock();
2278 }
2279
2280 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2281 {
2282     return FALSE;
2283 }
2284
2285 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2286                                       Pixmap pixmap, GC gc,
2287                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2288 {
2289     return FALSE;
2290 }
2291 #endif /* SONAME_LIBXRENDER */