winex11: Delete the palette and xrender static critical sections when unloading the...
[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  * Copyright 2011 Alexandre Julliard
7  *
8  * Some parts also:
9  * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <assert.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <stdlib.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "x11drv.h"
36 #include "winternl.h"
37 #include "wine/library.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
40
41 int using_client_side_fonts = FALSE;
42
43 WINE_DEFAULT_DEBUG_CHANNEL(xrender);
44
45 #ifdef SONAME_LIBXRENDER
46
47 static BOOL X11DRV_XRender_Installed = FALSE;
48
49 #include <X11/Xlib.h>
50 #include <X11/extensions/Xrender.h>
51
52 #ifndef RepeatNone  /* added in 0.10 */
53 #define RepeatNone    0
54 #define RepeatNormal  1
55 #define RepeatPad     2
56 #define RepeatReflect 3
57 #endif
58
59 enum wxr_format
60 {
61   WXR_FORMAT_MONO,
62   WXR_FORMAT_GRAY,
63   WXR_FORMAT_X1R5G5B5,
64   WXR_FORMAT_X1B5G5R5,
65   WXR_FORMAT_R5G6B5,
66   WXR_FORMAT_B5G6R5,
67   WXR_FORMAT_R8G8B8,
68   WXR_FORMAT_B8G8R8,
69   WXR_FORMAT_A8R8G8B8,
70   WXR_FORMAT_B8G8R8A8,
71   WXR_FORMAT_X8R8G8B8,
72   WXR_FORMAT_B8G8R8X8,
73   WXR_NB_FORMATS,
74   WXR_INVALID_FORMAT = WXR_NB_FORMATS
75 };
76
77 typedef struct wine_xrender_format_template
78 {
79     unsigned int depth;
80     unsigned int alpha;
81     unsigned int alphaMask;
82     unsigned int red;
83     unsigned int redMask;
84     unsigned int green;
85     unsigned int greenMask;
86     unsigned int blue;
87     unsigned int blueMask;
88 } WineXRenderFormatTemplate;
89
90 static const WineXRenderFormatTemplate wxr_formats_template[WXR_NB_FORMATS] =
91 {
92     /* Format               depth   alpha   mask    red     mask    green   mask    blue    mask*/
93 /* WXR_FORMAT_MONO     */ { 1,      0,      0x01,   0,      0,      0,      0,      0,      0       },
94 /* WXR_FORMAT_GRAY     */ { 8,      0,      0xff,   0,      0,      0,      0,      0,      0       },
95 /* WXR_FORMAT_X1R5G5B5 */ { 16,     0,      0,      10,     0x1f,   5,      0x1f,   0,      0x1f    },
96 /* WXR_FORMAT_X1B5G5R5 */ { 16,     0,      0,      0,      0x1f,   5,      0x1f,   10,     0x1f    },
97 /* WXR_FORMAT_R5G6B5   */ { 16,     0,      0,      11,     0x1f,   5,      0x3f,   0,      0x1f    },
98 /* WXR_FORMAT_B5G6R5   */ { 16,     0,      0,      0,      0x1f,   5,      0x3f,   11,     0x1f    },
99 /* WXR_FORMAT_R8G8B8   */ { 24,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
100 /* WXR_FORMAT_B8G8R8   */ { 24,     0,      0,      0,      0xff,   8,      0xff,   16,     0xff    },
101 /* WXR_FORMAT_A8R8G8B8 */ { 32,     24,     0xff,   16,     0xff,   8,      0xff,   0,      0xff    },
102 /* WXR_FORMAT_B8G8R8A8 */ { 32,     0,      0xff,   8,      0xff,   16,     0xff,   24,     0xff    },
103 /* WXR_FORMAT_X8R8G8B8 */ { 32,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
104 /* WXR_FORMAT_B8G8R8X8 */ { 32,     0,      0,      8,      0xff,   16,     0xff,   24,     0xff    },
105 };
106
107 static const ColorShifts wxr_color_shifts[WXR_NB_FORMATS] =
108 {
109     /* format                phys red    phys green  phys blue   log red     log green   log blue */
110 /* WXR_FORMAT_MONO     */ { { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 }  },
111 /* WXR_FORMAT_GRAY     */ { { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 }  },
112 /* WXR_FORMAT_X1R5G5B5 */ { {10,5,31},  { 5,5,31},  { 0,5,31},  {10,5,31},  { 5,5,31},  { 0,5,31}  },
113 /* WXR_FORMAT_X1B5G5R5 */ { { 0,5,31},  { 5,5,31},  {10,5,31},  { 0,5,31},  { 5,5,31},  {10,5,31}  },
114 /* WXR_FORMAT_R5G6B5   */ { {11,5,31},  { 5,6,63},  { 0,5,31},  {11,5,31},  { 5,6,63},  { 0,5,31}  },
115 /* WXR_FORMAT_B5G6R5   */ { { 0,5,31},  { 5,6,63},  {11,5,31},  { 0,5,31},  { 5,6,63},  {11,5,31}  },
116 /* WXR_FORMAT_R8G8B8   */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
117 /* WXR_FORMAT_B8G8R8   */ { { 0,8,255}, { 8,8,255}, {16,8,255}, { 0,8,255}, { 8,8,255}, {16,8,255} },
118 /* WXR_FORMAT_A8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
119 /* WXR_FORMAT_B8G8R8A8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
120 /* WXR_FORMAT_X8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
121 /* WXR_FORMAT_B8G8R8X8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
122 };
123
124 static enum wxr_format default_format = WXR_INVALID_FORMAT;
125 static XRenderPictFormat *pict_formats[WXR_NB_FORMATS + 1 /* invalid format */];
126
127 typedef struct
128 {
129     LOGFONTW lf;
130     XFORM    xform;
131     SIZE     devsize;  /* size in device coords */
132     DWORD    hash;
133 } LFANDSIZE;
134
135 #define INITIAL_REALIZED_BUF_SIZE 128
136
137 typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
138
139 typedef struct
140 {
141     GlyphSet glyphset;
142     XRenderPictFormat *font_format;
143     int nrealized;
144     BOOL *realized;
145     void **bitmaps;
146     XGlyphInfo *gis;
147 } gsCacheEntryFormat;
148
149 typedef struct
150 {
151     LFANDSIZE lfsz;
152     AA_Type aa_default;
153     gsCacheEntryFormat * format[AA_MAXVALUE];
154     INT count;
155     INT next;
156 } gsCacheEntry;
157
158 struct xrender_physdev
159 {
160     struct gdi_physdev dev;
161     X11DRV_PDEVICE    *x11dev;
162     enum wxr_format    format;
163     int                cache_index;
164     BOOL               update_clip;
165     Picture            pict;
166     Picture            pict_src;
167     XRenderPictFormat *pict_format;
168 };
169
170 static inline struct xrender_physdev *get_xrender_dev( PHYSDEV dev )
171 {
172     return (struct xrender_physdev *)dev;
173 }
174
175 static const struct gdi_dc_funcs xrender_funcs;
176
177 static gsCacheEntry *glyphsetCache = NULL;
178 static DWORD glyphsetCacheSize = 0;
179 static INT lastfree = -1;
180 static INT mru = -1;
181
182 #define INIT_CACHE_SIZE 10
183
184 static int antialias = 1;
185
186 static void *xrender_handle;
187
188 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
189 MAKE_FUNCPTR(XRenderAddGlyphs)
190 MAKE_FUNCPTR(XRenderComposite)
191 MAKE_FUNCPTR(XRenderCompositeText16)
192 MAKE_FUNCPTR(XRenderCreateGlyphSet)
193 MAKE_FUNCPTR(XRenderCreatePicture)
194 MAKE_FUNCPTR(XRenderFillRectangle)
195 MAKE_FUNCPTR(XRenderFindFormat)
196 MAKE_FUNCPTR(XRenderFindVisualFormat)
197 MAKE_FUNCPTR(XRenderFreeGlyphSet)
198 MAKE_FUNCPTR(XRenderFreePicture)
199 MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
200 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
201 MAKE_FUNCPTR(XRenderSetPictureTransform)
202 #endif
203 MAKE_FUNCPTR(XRenderQueryExtension)
204
205 #ifdef SONAME_LIBFONTCONFIG
206 #include <fontconfig/fontconfig.h>
207 MAKE_FUNCPTR(FcConfigSubstitute)
208 MAKE_FUNCPTR(FcDefaultSubstitute)
209 MAKE_FUNCPTR(FcFontMatch)
210 MAKE_FUNCPTR(FcInit)
211 MAKE_FUNCPTR(FcPatternCreate)
212 MAKE_FUNCPTR(FcPatternDestroy)
213 MAKE_FUNCPTR(FcPatternAddInteger)
214 MAKE_FUNCPTR(FcPatternAddString)
215 MAKE_FUNCPTR(FcPatternGetBool)
216 MAKE_FUNCPTR(FcPatternGetInteger)
217 MAKE_FUNCPTR(FcPatternGetString)
218 static void *fontconfig_handle;
219 static BOOL fontconfig_installed;
220 #endif
221
222 #undef MAKE_FUNCPTR
223
224 static CRITICAL_SECTION xrender_cs;
225 static CRITICAL_SECTION_DEBUG critsect_debug =
226 {
227     0, 0, &xrender_cs,
228     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
229       0, 0, { (DWORD_PTR)(__FILE__ ": xrender_cs") }
230 };
231 static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
232
233 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
234           ( ( (ULONG)_x4 << 24 ) |     \
235             ( (ULONG)_x3 << 16 ) |     \
236             ( (ULONG)_x2 <<  8 ) |     \
237               (ULONG)_x1         )
238
239 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
240
241 #define GASP_GRIDFIT 0x01
242 #define GASP_DOGRAY  0x02
243
244 #ifdef WORDS_BIGENDIAN
245 #define get_be_word(x) (x)
246 #define NATIVE_BYTE_ORDER MSBFirst
247 #else
248 #define get_be_word(x) RtlUshortByteSwap(x)
249 #define NATIVE_BYTE_ORDER LSBFirst
250 #endif
251
252 static BOOL has_alpha( enum wxr_format format )
253 {
254     return (format == WXR_FORMAT_A8R8G8B8 || format == WXR_FORMAT_B8G8R8A8);
255 }
256
257 static enum wxr_format get_format_without_alpha( enum wxr_format format )
258 {
259     switch (format)
260     {
261     case WXR_FORMAT_A8R8G8B8: return WXR_FORMAT_X8R8G8B8;
262     case WXR_FORMAT_B8G8R8A8: return WXR_FORMAT_B8G8R8X8;
263     default: return format;
264     }
265 }
266
267 static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
268 {
269     templ->id = 0;
270     templ->type = PictTypeDirect;
271     templ->depth = fmt->depth;
272     templ->direct.alpha = fmt->alpha;
273     templ->direct.alphaMask = fmt->alphaMask;
274     templ->direct.red = fmt->red;
275     templ->direct.redMask = fmt->redMask;
276     templ->direct.green = fmt->green;
277     templ->direct.greenMask = fmt->greenMask;
278     templ->direct.blue = fmt->blue;
279     templ->direct.blueMask = fmt->blueMask;
280     templ->colormap = 0;
281
282     *mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
283
284     return TRUE;
285 }
286
287 static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
288 {
289     if(fmt->depth != screen_depth)
290         return FALSE;
291     if( (fmt->redMask << fmt->red) != visual->red_mask)
292         return FALSE;
293     if( (fmt->greenMask << fmt->green) != visual->green_mask)
294         return FALSE;
295     if( (fmt->blueMask << fmt->blue) != visual->blue_mask)
296         return FALSE;
297
298     /* We never select a default ARGB visual */
299     if(fmt->alphaMask)
300         return FALSE;
301
302     return TRUE;
303 }
304
305 static int load_xrender_formats(void)
306 {
307     int count = 0;
308     unsigned int i;
309
310     for (i = 0; i < WXR_NB_FORMATS; i++)
311     {
312         XRenderPictFormat templ;
313
314         if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
315         {
316             wine_tsx11_lock();
317             pict_formats[i] = pXRenderFindVisualFormat(gdi_display, visual);
318             if (!pict_formats[i])
319             {
320                 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
321                 if (visual->class == DirectColor)
322                 {
323                     XVisualInfo info;
324                     if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
325                                           screen_depth, TrueColor, &info ))
326                     {
327                         pict_formats[i] = pXRenderFindVisualFormat(gdi_display, info.visual);
328                         if (pict_formats[i]) visual = info.visual;
329                     }
330                 }
331             }
332             wine_tsx11_unlock();
333             if (pict_formats[i]) default_format = i;
334         }
335         else
336         {
337             unsigned long mask = 0;
338             get_xrender_template(&wxr_formats_template[i], &templ, &mask);
339
340             wine_tsx11_lock();
341             pict_formats[i] = pXRenderFindFormat(gdi_display, mask, &templ, 0);
342             wine_tsx11_unlock();
343         }
344         if (pict_formats[i])
345         {
346             count++;
347             TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats[i]->id, i);
348         }
349     }
350     return count;
351 }
352
353 /***********************************************************************
354  *   X11DRV_XRender_Init
355  *
356  * Let's see if our XServer has the extension available
357  *
358  */
359 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
360 {
361     int event_base, i;
362
363     if (client_side_with_render &&
364         (xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0)))
365     {
366
367 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
368 LOAD_FUNCPTR(XRenderAddGlyphs)
369 LOAD_FUNCPTR(XRenderComposite)
370 LOAD_FUNCPTR(XRenderCompositeText16)
371 LOAD_FUNCPTR(XRenderCreateGlyphSet)
372 LOAD_FUNCPTR(XRenderCreatePicture)
373 LOAD_FUNCPTR(XRenderFillRectangle)
374 LOAD_FUNCPTR(XRenderFindFormat)
375 LOAD_FUNCPTR(XRenderFindVisualFormat)
376 LOAD_FUNCPTR(XRenderFreeGlyphSet)
377 LOAD_FUNCPTR(XRenderFreePicture)
378 LOAD_FUNCPTR(XRenderSetPictureClipRectangles)
379 LOAD_FUNCPTR(XRenderQueryExtension)
380 #undef LOAD_FUNCPTR
381 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
382 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0);
383 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform)
384 #undef LOAD_OPTIONAL_FUNCPTR
385 #endif
386
387         wine_tsx11_lock();
388         X11DRV_XRender_Installed = pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base);
389         wine_tsx11_unlock();
390         if(X11DRV_XRender_Installed) {
391             TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
392             if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
393             {
394                 wine_tsx11_unlock();
395                 WINE_MESSAGE(
396                     "Wine has detected that you probably have a buggy version\n"
397                     "of libXrender.so .  Because of this client side font rendering\n"
398                     "will be disabled.  Please upgrade this library.\n");
399                 X11DRV_XRender_Installed = FALSE;
400                 return NULL;
401             }
402
403             if (!visual->red_mask || !visual->green_mask || !visual->blue_mask) {
404                 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
405                 X11DRV_XRender_Installed = FALSE;
406             }
407         }
408     }
409
410 #ifdef SONAME_LIBFONTCONFIG
411     if ((fontconfig_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0)))
412     {
413 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(fontconfig_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
414         LOAD_FUNCPTR(FcConfigSubstitute);
415         LOAD_FUNCPTR(FcDefaultSubstitute);
416         LOAD_FUNCPTR(FcFontMatch);
417         LOAD_FUNCPTR(FcInit);
418         LOAD_FUNCPTR(FcPatternCreate);
419         LOAD_FUNCPTR(FcPatternDestroy);
420         LOAD_FUNCPTR(FcPatternAddInteger);
421         LOAD_FUNCPTR(FcPatternAddString);
422         LOAD_FUNCPTR(FcPatternGetBool);
423         LOAD_FUNCPTR(FcPatternGetInteger);
424         LOAD_FUNCPTR(FcPatternGetString);
425 #undef LOAD_FUNCPTR
426         fontconfig_installed = pFcInit();
427     }
428     else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG "\n" );
429 #endif
430
431 sym_not_found:
432     if(X11DRV_XRender_Installed || client_side_with_core)
433     {
434         glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
435                                   sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
436
437         glyphsetCacheSize = INIT_CACHE_SIZE;
438         lastfree = 0;
439         for(i = 0; i < INIT_CACHE_SIZE; i++) {
440           glyphsetCache[i].next = i + 1;
441           glyphsetCache[i].count = -1;
442         }
443         glyphsetCache[i-1].next = -1;
444         using_client_side_fonts = 1;
445
446         if(!X11DRV_XRender_Installed) {
447             TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
448             if(screen_depth <= 8 || !client_side_antialias_with_core)
449                 antialias = 0;
450         } else {
451             if(screen_depth <= 8 || !client_side_antialias_with_render)
452                 antialias = 0;
453         }
454         return &xrender_funcs;
455     }
456     TRACE("Using X11 core fonts\n");
457     return NULL;
458 }
459
460 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
461 static void get_xrender_color( XRenderPictFormat *pf, int src_color, XRenderColor *dst_color )
462 {
463     if(pf->direct.redMask)
464         dst_color->red = ((src_color >> pf->direct.red) & pf->direct.redMask) * 65535/pf->direct.redMask;
465     else
466        dst_color->red = 0;
467
468     if(pf->direct.greenMask)
469         dst_color->green = ((src_color >> pf->direct.green) & pf->direct.greenMask) * 65535/pf->direct.greenMask;
470     else
471         dst_color->green = 0;
472
473     if(pf->direct.blueMask)
474         dst_color->blue = ((src_color >> pf->direct.blue) & pf->direct.blueMask) * 65535/pf->direct.blueMask;
475     else
476         dst_color->blue = 0;
477
478     dst_color->alpha = 0xffff;
479 }
480
481 static enum wxr_format get_xrender_format_from_color_shifts(int depth, ColorShifts *shifts)
482 {
483     int redMask, greenMask, blueMask;
484     unsigned int i;
485
486     if (depth == 1) return WXR_FORMAT_MONO;
487
488     /* physDevs of a depth <=8, don't have color_shifts set and XRender can't handle those except for 1-bit */
489     if (!shifts) return default_format;
490
491     redMask   = shifts->physicalRed.max << shifts->physicalRed.shift;
492     greenMask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
493     blueMask  = shifts->physicalBlue.max << shifts->physicalBlue.shift;
494
495     /* Try to locate a format which matches the specification of the dibsection. */
496     for(i = 0; i < WXR_NB_FORMATS; i++)
497     {
498         if( depth     == wxr_formats_template[i].depth &&
499             redMask   == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
500             greenMask == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
501             blueMask  == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue) )
502             return i;
503     }
504
505     /* This should not happen because when we reach 'shifts' must have been set and we only allows shifts which are backed by X */
506     ERR("No XRender format found for %u %08x/%08x/%08x\n", depth, redMask, greenMask, blueMask);
507     return WXR_INVALID_FORMAT;
508 }
509
510 static enum wxr_format get_xrender_format_from_bitmapinfo( const BITMAPINFO *info )
511 {
512     if (info->bmiHeader.biPlanes != 1) return WXR_INVALID_FORMAT;
513
514     switch (info->bmiHeader.biBitCount)
515     {
516     case 1:
517         return WXR_FORMAT_MONO;
518     case 4:
519     case 8:
520         break;
521     case 24:
522         if (info->bmiHeader.biCompression != BI_RGB) break;
523         return WXR_FORMAT_R8G8B8;
524     case 16:
525     case 32:
526         if (info->bmiHeader.biCompression == BI_BITFIELDS)
527         {
528             DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
529             unsigned int i;
530
531             for (i = 0; i < WXR_NB_FORMATS; i++)
532             {
533                 if (info->bmiHeader.biBitCount == wxr_formats_template[i].depth &&
534                     colors[0] == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
535                     colors[1] == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
536                     colors[2] == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue))
537                     return i;
538             }
539             break;
540         }
541         if (info->bmiHeader.biCompression != BI_RGB) break;
542         return (info->bmiHeader.biBitCount == 16) ? WXR_FORMAT_X1R5G5B5 : WXR_FORMAT_A8R8G8B8;
543     }
544     return WXR_INVALID_FORMAT;
545 }
546
547 static enum wxr_format get_bitmap_format( int bpp )
548 {
549     enum wxr_format format = WXR_INVALID_FORMAT;
550
551     if (bpp == screen_bpp)
552     {
553         switch (bpp)
554         {
555         case 16: format = WXR_FORMAT_R5G6B5; break;
556         case 24: format = WXR_FORMAT_R8G8B8; break;
557         case 32: format = WXR_FORMAT_A8R8G8B8; break;
558         }
559     }
560     return format;
561 }
562
563 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
564 static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
565 {
566 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
567     XTransform xform = {{
568         { XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(xoffset) },
569         { XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(yoffset) },
570         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
571     }};
572
573     pXRenderSetPictureTransform(gdi_display, src_pict, &xform);
574 #endif
575 }
576
577 /* check if we can use repeating instead of scaling for the specified source DC */
578 static BOOL use_source_repeat( struct xrender_physdev *dev )
579 {
580     return (dev->x11dev->bitmap &&
581             dev->x11dev->drawable_rect.right - dev->x11dev->drawable_rect.left == 1 &&
582             dev->x11dev->drawable_rect.bottom - dev->x11dev->drawable_rect.top == 1);
583 }
584
585 static Picture get_xrender_picture( struct xrender_physdev *dev, HRGN clip_rgn, const RECT *clip_rect )
586 {
587     if (!dev->pict && dev->pict_format)
588     {
589         XRenderPictureAttributes pa;
590
591         wine_tsx11_lock();
592         pa.subwindow_mode = IncludeInferiors;
593         dev->pict = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
594                                            dev->pict_format, CPSubwindowMode, &pa );
595         wine_tsx11_unlock();
596         TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
597                dev->pict, dev->dev.hdc, dev->x11dev->drawable );
598         dev->update_clip = TRUE;
599     }
600
601     if (dev->update_clip)
602     {
603         RGNDATA *clip_data;
604         HRGN rgn = 0;
605
606         if (clip_rect)
607         {
608             rgn = CreateRectRgnIndirect( clip_rect );
609             if (clip_rgn) CombineRgn( rgn, rgn, clip_rgn, RGN_AND );
610             CombineRgn( rgn, rgn, dev->x11dev->region, RGN_AND );
611         }
612         else if (clip_rgn)
613         {
614             rgn = CreateRectRgn( 0, 0, 0, 0 );
615             CombineRgn( rgn, clip_rgn, dev->x11dev->region, RGN_AND );
616         }
617
618         if ((clip_data = X11DRV_GetRegionData( rgn ? rgn : dev->x11dev->region, 0 )))
619         {
620             wine_tsx11_lock();
621             pXRenderSetPictureClipRectangles( gdi_display, dev->pict,
622                                               dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top,
623                                               (XRectangle *)clip_data->Buffer, clip_data->rdh.nCount );
624             wine_tsx11_unlock();
625             HeapFree( GetProcessHeap(), 0, clip_data );
626         }
627         dev->update_clip = (rgn != 0);  /* have to update again if we are using a custom region */
628         if (rgn) DeleteObject( rgn );
629     }
630     return dev->pict;
631 }
632
633 static Picture get_xrender_picture_source( struct xrender_physdev *dev, BOOL repeat )
634 {
635     if (!dev->pict_src && dev->pict_format)
636     {
637         XRenderPictureAttributes pa;
638
639         wine_tsx11_lock();
640         pa.subwindow_mode = IncludeInferiors;
641         pa.repeat = repeat ? RepeatNormal : RepeatNone;
642         dev->pict_src = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
643                                                dev->pict_format, CPSubwindowMode|CPRepeat, &pa );
644         wine_tsx11_unlock();
645
646         TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
647               dev->pict_src, dev->dev.hdc, dev->x11dev->drawable, pa.repeat);
648     }
649
650     return dev->pict_src;
651 }
652
653 static void free_xrender_picture( struct xrender_physdev *dev )
654 {
655     if (dev->pict || dev->pict_src)
656     {
657         wine_tsx11_lock();
658         XFlush( gdi_display );
659         if (dev->pict)
660         {
661             TRACE("freeing pict = %lx dc = %p\n", dev->pict, dev->dev.hdc);
662             pXRenderFreePicture(gdi_display, dev->pict);
663             dev->pict = 0;
664         }
665         if(dev->pict_src)
666         {
667             TRACE("freeing pict = %lx dc = %p\n", dev->pict_src, dev->dev.hdc);
668             pXRenderFreePicture(gdi_display, dev->pict_src);
669             dev->pict_src = 0;
670         }
671         wine_tsx11_unlock();
672     }
673 }
674
675 /* return a mask picture used to force alpha to 0 */
676 static Picture get_no_alpha_mask(void)
677 {
678     static Pixmap pixmap;
679     static Picture pict;
680
681     wine_tsx11_lock();
682     if (!pict)
683     {
684         XRenderPictureAttributes pa;
685         XRenderColor col;
686
687         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
688         pa.repeat = RepeatNormal;
689         pa.component_alpha = True;
690         pict = pXRenderCreatePicture( gdi_display, pixmap, pict_formats[WXR_FORMAT_A8R8G8B8],
691                                       CPRepeat|CPComponentAlpha, &pa );
692         col.red = col.green = col.blue = 0xffff;
693         col.alpha = 0;
694         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
695     }
696     wine_tsx11_unlock();
697     return pict;
698 }
699
700 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
701 {
702   if(p1->hash != p2->hash) return TRUE;
703   if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE;
704   if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE;
705   if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
706   return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName);
707 }
708
709 #if 0
710 static void walk_cache(void)
711 {
712   int i;
713
714   EnterCriticalSection(&xrender_cs);
715   for(i=mru; i >= 0; i = glyphsetCache[i].next)
716     TRACE("item %d\n", i);
717   LeaveCriticalSection(&xrender_cs);
718 }
719 #endif
720
721 static int LookupEntry(LFANDSIZE *plfsz)
722 {
723   int i, prev_i = -1;
724
725   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
726     TRACE("%d\n", i);
727     if(glyphsetCache[i].count == -1) break; /* reached free list so stop */
728
729     if(!fontcmp(&glyphsetCache[i].lfsz, plfsz)) {
730       glyphsetCache[i].count++;
731       if(prev_i >= 0) {
732         glyphsetCache[prev_i].next = glyphsetCache[i].next;
733         glyphsetCache[i].next = mru;
734         mru = i;
735       }
736       TRACE("found font in cache %d\n", i);
737       return i;
738     }
739     prev_i = i;
740   }
741   TRACE("font not in cache\n");
742   return -1;
743 }
744
745 static void FreeEntry(int entry)
746 {
747     int i, format;
748   
749     for(format = 0; format < AA_MAXVALUE; format++) {
750         gsCacheEntryFormat * formatEntry;
751
752         if( !glyphsetCache[entry].format[format] )
753             continue;
754
755         formatEntry = glyphsetCache[entry].format[format];
756
757         if(formatEntry->glyphset) {
758             wine_tsx11_lock();
759             pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
760             wine_tsx11_unlock();
761             formatEntry->glyphset = 0;
762         }
763         if(formatEntry->nrealized) {
764             HeapFree(GetProcessHeap(), 0, formatEntry->realized);
765             formatEntry->realized = NULL;
766             if(formatEntry->bitmaps) {
767                 for(i = 0; i < formatEntry->nrealized; i++)
768                     HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps[i]);
769                 HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps);
770                 formatEntry->bitmaps = NULL;
771             }
772             HeapFree(GetProcessHeap(), 0, formatEntry->gis);
773             formatEntry->gis = NULL;
774             formatEntry->nrealized = 0;
775         }
776
777         HeapFree(GetProcessHeap(), 0, formatEntry);
778         glyphsetCache[entry].format[format] = NULL;
779     }
780 }
781
782 static int AllocEntry(void)
783 {
784   int best = -1, prev_best = -1, i, prev_i = -1;
785
786   if(lastfree >= 0) {
787     assert(glyphsetCache[lastfree].count == -1);
788     glyphsetCache[lastfree].count = 1;
789     best = lastfree;
790     lastfree = glyphsetCache[lastfree].next;
791     assert(best != mru);
792     glyphsetCache[best].next = mru;
793     mru = best;
794
795     TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
796     return mru;
797   }
798
799   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
800     if(glyphsetCache[i].count == 0) {
801       best = i;
802       prev_best = prev_i;
803     }
804     prev_i = i;
805   }
806
807   if(best >= 0) {
808     TRACE("freeing unused glyphset at cache %d\n", best);
809     FreeEntry(best);
810     glyphsetCache[best].count = 1;
811     if(prev_best >= 0) {
812       glyphsetCache[prev_best].next = glyphsetCache[best].next;
813       glyphsetCache[best].next = mru;
814       mru = best;
815     } else {
816       assert(mru == best);
817     }
818     return mru;
819   }
820
821   TRACE("Growing cache\n");
822   
823   if (glyphsetCache)
824     glyphsetCache = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
825                               glyphsetCache,
826                               (glyphsetCacheSize + INIT_CACHE_SIZE)
827                               * sizeof(*glyphsetCache));
828   else
829     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
830                               (glyphsetCacheSize + INIT_CACHE_SIZE)
831                               * sizeof(*glyphsetCache));
832
833   for(best = i = glyphsetCacheSize; i < glyphsetCacheSize + INIT_CACHE_SIZE;
834       i++) {
835     glyphsetCache[i].next = i + 1;
836     glyphsetCache[i].count = -1;
837   }
838   glyphsetCache[i-1].next = -1;
839   glyphsetCacheSize += INIT_CACHE_SIZE;
840
841   lastfree = glyphsetCache[best].next;
842   glyphsetCache[best].count = 1;
843   glyphsetCache[best].next = mru;
844   mru = best;
845   TRACE("new free cache slot at %d\n", mru);
846   return mru;
847 }
848
849 static BOOL get_gasp_flags(HDC hdc, WORD *flags)
850 {
851     DWORD size;
852     WORD *gasp, *buffer;
853     WORD num_recs;
854     DWORD ppem;
855     TEXTMETRICW tm;
856
857     *flags = 0;
858
859     size = GetFontData(hdc, MS_GASP_TAG,  0, NULL, 0);
860     if(size == GDI_ERROR)
861         return FALSE;
862
863     gasp = buffer = HeapAlloc(GetProcessHeap(), 0, size);
864     GetFontData(hdc, MS_GASP_TAG,  0, gasp, size);
865
866     GetTextMetricsW(hdc, &tm);
867     ppem = abs(X11DRV_YWStoDS(hdc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading));
868
869     gasp++;
870     num_recs = get_be_word(*gasp);
871     gasp++;
872     while(num_recs--)
873     {
874         *flags = get_be_word(*(gasp + 1));
875         if(ppem <= get_be_word(*gasp))
876             break;
877         gasp += 2;
878     }
879     TRACE("got flags %04x for ppem %d\n", *flags, ppem);
880
881     HeapFree(GetProcessHeap(), 0, buffer);
882     return TRUE;
883 }
884
885 static AA_Type get_antialias_type( HDC hdc, BOOL subpixel, BOOL hinter )
886 {
887     AA_Type ret;
888     WORD flags;
889     UINT font_smoothing_type, font_smoothing_orientation;
890
891     if (X11DRV_XRender_Installed && subpixel &&
892         SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE, 0, &font_smoothing_type, 0) &&
893         font_smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
894     {
895         if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION, 0,
896                                     &font_smoothing_orientation, 0) &&
897              font_smoothing_orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
898         {
899             ret = AA_BGR;
900         }
901         else
902             ret = AA_RGB;
903         /*FIXME
904           If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
905           But, Wine's subpixel rendering can support the portrait mode.
906          */
907     }
908     else if (!hinter || !get_gasp_flags(hdc, &flags) || flags & GASP_DOGRAY)
909         ret = AA_Grey;
910     else
911         ret = AA_None;
912
913     return ret;
914 }
915
916 static int GetCacheEntry( HDC hdc, LFANDSIZE *plfsz )
917 {
918     int ret;
919     int format;
920     gsCacheEntry *entry;
921     static int hinter = -1;
922     static int subpixel = -1;
923     BOOL font_smoothing;
924
925     if((ret = LookupEntry(plfsz)) != -1) return ret;
926
927     ret = AllocEntry();
928     entry = glyphsetCache + ret;
929     entry->lfsz = *plfsz;
930     for( format = 0; format < AA_MAXVALUE; format++ ) {
931         assert( !entry->format[format] );
932     }
933
934     if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY)
935     {
936         if(hinter == -1 || subpixel == -1)
937         {
938             RASTERIZER_STATUS status;
939             GetRasterizerCaps(&status, sizeof(status));
940             hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
941             subpixel = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
942         }
943
944         switch (plfsz->lf.lfQuality)
945         {
946             case ANTIALIASED_QUALITY:
947                 entry->aa_default = get_antialias_type( hdc, FALSE, hinter );
948                 return ret;  /* ignore further configuration */
949             case CLEARTYPE_QUALITY:
950             case CLEARTYPE_NATURAL_QUALITY:
951                 entry->aa_default = get_antialias_type( hdc, subpixel, hinter );
952                 break;
953             case DEFAULT_QUALITY:
954             case DRAFT_QUALITY:
955             case PROOF_QUALITY:
956             default:
957                 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0) &&
958                      font_smoothing)
959                 {
960                     entry->aa_default = get_antialias_type( hdc, subpixel, hinter );
961                 }
962                 else
963                     entry->aa_default = AA_None;
964                 break;
965         }
966
967         font_smoothing = TRUE;  /* default to enabled */
968 #ifdef SONAME_LIBFONTCONFIG
969         if (fontconfig_installed)
970         {
971             FcPattern *match, *pattern;
972             FcResult result;
973             char family[LF_FACESIZE * 4];
974
975 #if defined(__i386__) && defined(__GNUC__)
976             /* fontconfig generates floating point exceptions, mask them */
977             WORD cw, default_cw = 0x37f;
978             __asm__ __volatile__("fnstcw %0; fldcw %1" : "=m" (cw) : "m" (default_cw));
979 #endif
980
981             WideCharToMultiByte( CP_UTF8, 0, plfsz->lf.lfFaceName, -1, family, sizeof(family), NULL, NULL );
982             pattern = pFcPatternCreate();
983             pFcPatternAddString( pattern, FC_FAMILY, (FcChar8 *)family );
984             if (plfsz->lf.lfWeight != FW_DONTCARE)
985             {
986                 int weight;
987                 switch (plfsz->lf.lfWeight)
988                 {
989                 case FW_THIN:       weight = FC_WEIGHT_THIN; break;
990                 case FW_EXTRALIGHT: weight = FC_WEIGHT_EXTRALIGHT; break;
991                 case FW_LIGHT:      weight = FC_WEIGHT_LIGHT; break;
992                 case FW_NORMAL:     weight = FC_WEIGHT_NORMAL; break;
993                 case FW_MEDIUM:     weight = FC_WEIGHT_MEDIUM; break;
994                 case FW_SEMIBOLD:   weight = FC_WEIGHT_SEMIBOLD; break;
995                 case FW_BOLD:       weight = FC_WEIGHT_BOLD; break;
996                 case FW_EXTRABOLD:  weight = FC_WEIGHT_EXTRABOLD; break;
997                 case FW_HEAVY:      weight = FC_WEIGHT_HEAVY; break;
998                 default:            weight = (plfsz->lf.lfWeight - 80) / 4; break;
999                 }
1000                 pFcPatternAddInteger( pattern, FC_WEIGHT, weight );
1001             }
1002             pFcPatternAddInteger( pattern, FC_SLANT, plfsz->lf.lfItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
1003             pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
1004             pFcDefaultSubstitute( pattern );
1005             if ((match = pFcFontMatch( NULL, pattern, &result )))
1006             {
1007                 int rgba;
1008                 FcBool antialias;
1009
1010                 if (pFcPatternGetBool( match, FC_ANTIALIAS, 0, &antialias ) != FcResultMatch)
1011                     antialias = TRUE;
1012                 if (pFcPatternGetInteger( match, FC_RGBA, 0, &rgba ) == FcResultMatch)
1013                 {
1014                     FcChar8 *file;
1015                     if (pFcPatternGetString( match, FC_FILE, 0, &file ) != FcResultMatch) file = NULL;
1016
1017                     TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
1018                            rgba, antialias, debugstr_w(plfsz->lf.lfFaceName), debugstr_a((char *)file) );
1019
1020                     switch (rgba)
1021                     {
1022                     case FC_RGBA_RGB:  entry->aa_default = AA_RGB; break;
1023                     case FC_RGBA_BGR:  entry->aa_default = AA_BGR; break;
1024                     case FC_RGBA_VRGB: entry->aa_default = AA_VRGB; break;
1025                     case FC_RGBA_VBGR: entry->aa_default = AA_VBGR; break;
1026                     case FC_RGBA_NONE: entry->aa_default = AA_Grey; break;
1027                     }
1028                 }
1029                 if (!antialias) font_smoothing = FALSE;
1030                 pFcPatternDestroy( match );
1031             }
1032             pFcPatternDestroy( pattern );
1033
1034 #if defined(__i386__) && defined(__GNUC__)
1035             __asm__ __volatile__("fnclex; fldcw %0" : : "m" (cw));
1036 #endif
1037         }
1038 #endif  /* SONAME_LIBFONTCONFIG */
1039
1040         /* now check Xft resources */
1041         {
1042             char *value;
1043             BOOL antialias = TRUE;
1044
1045             wine_tsx11_lock();
1046             if ((value = XGetDefault( gdi_display, "Xft", "antialias" )))
1047             {
1048                 if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
1049                     value[0] == '0' || !strcasecmp( value, "off" ))
1050                     antialias = FALSE;
1051             }
1052             if ((value = XGetDefault( gdi_display, "Xft", "rgba" )))
1053             {
1054                 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value, antialias );
1055                 if (!strcmp( value, "rgb" )) entry->aa_default = AA_RGB;
1056                 else if (!strcmp( value, "bgr" )) entry->aa_default = AA_BGR;
1057                 else if (!strcmp( value, "vrgb" )) entry->aa_default = AA_VRGB;
1058                 else if (!strcmp( value, "vbgr" )) entry->aa_default = AA_VBGR;
1059                 else if (!strcmp( value, "none" )) entry->aa_default = AA_Grey;
1060             }
1061             wine_tsx11_unlock();
1062             if (!antialias) font_smoothing = FALSE;
1063         }
1064
1065         if (!font_smoothing) entry->aa_default = AA_None;
1066
1067         /* we can't support subpixel without xrender */
1068         if (!X11DRV_XRender_Installed && entry->aa_default > AA_Grey) entry->aa_default = AA_Grey;
1069     }
1070     else
1071         entry->aa_default = AA_None;
1072
1073     return ret;
1074 }
1075
1076 static void dec_ref_cache(int index)
1077 {
1078     assert(index >= 0);
1079     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
1080     assert(glyphsetCache[index].count > 0);
1081     glyphsetCache[index].count--;
1082 }
1083
1084 static void lfsz_calc_hash(LFANDSIZE *plfsz)
1085 {
1086   DWORD hash = 0, *ptr, two_chars;
1087   WORD *pwc;
1088   int i;
1089
1090   hash ^= plfsz->devsize.cx;
1091   hash ^= plfsz->devsize.cy;
1092   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
1093     hash ^= *ptr;
1094   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
1095     hash ^= *ptr;
1096   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
1097     two_chars = *ptr;
1098     pwc = (WCHAR *)&two_chars;
1099     if(!*pwc) break;
1100     *pwc = toupperW(*pwc);
1101     pwc++;
1102     *pwc = toupperW(*pwc);
1103     hash ^= two_chars;
1104     if(!*pwc) break;
1105   }
1106   plfsz->hash = hash;
1107   return;
1108 }
1109
1110 /***********************************************************************
1111  *   X11DRV_XRender_Finalize
1112  */
1113 void X11DRV_XRender_Finalize(void)
1114 {
1115     int i;
1116
1117     EnterCriticalSection(&xrender_cs);
1118     for(i = mru; i >= 0; i = glyphsetCache[i].next)
1119         FreeEntry(i);
1120     LeaveCriticalSection(&xrender_cs);
1121     DeleteCriticalSection(&xrender_cs);
1122 }
1123
1124 /**********************************************************************
1125  *           xrenderdrv_SelectFont
1126  */
1127 static HFONT xrenderdrv_SelectFont( PHYSDEV dev, HFONT hfont )
1128 {
1129     struct xrender_physdev *physdev = get_xrender_dev( dev );
1130     PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont );
1131     HFONT ret = next->funcs->pSelectFont( next, hfont );
1132
1133     if (!ret) return 0;
1134
1135     if (physdev->x11dev->has_gdi_font)
1136     {
1137         LFANDSIZE lfsz;
1138
1139         GetObjectW( hfont, sizeof(lfsz.lf), &lfsz.lf );
1140
1141         TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1142               lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
1143               lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
1144         lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
1145         lfsz.devsize.cx = X11DRV_XWStoDS( dev->hdc, lfsz.lf.lfWidth );
1146         lfsz.devsize.cy = X11DRV_YWStoDS( dev->hdc, lfsz.lf.lfHeight );
1147
1148         GetTransform( dev->hdc, 0x204, &lfsz.xform );
1149         TRACE("font transform %f %f %f %f\n", lfsz.xform.eM11, lfsz.xform.eM12,
1150               lfsz.xform.eM21, lfsz.xform.eM22);
1151
1152         /* Not used fields, would break hashing */
1153         lfsz.xform.eDx = lfsz.xform.eDy = 0;
1154
1155         lfsz_calc_hash(&lfsz);
1156
1157         EnterCriticalSection(&xrender_cs);
1158         if (physdev->cache_index != -1)
1159             dec_ref_cache( physdev->cache_index );
1160         physdev->cache_index = GetCacheEntry( dev->hdc, &lfsz );
1161         LeaveCriticalSection(&xrender_cs);
1162     }
1163     else
1164     {
1165         EnterCriticalSection( &xrender_cs );
1166         if (physdev->cache_index != -1) dec_ref_cache( physdev->cache_index );
1167         physdev->cache_index = -1;
1168         LeaveCriticalSection( &xrender_cs );
1169     }
1170     return ret;
1171 }
1172
1173 static BOOL create_xrender_dc( PHYSDEV *pdev, enum wxr_format format )
1174 {
1175     X11DRV_PDEVICE *x11dev = get_x11drv_dev( *pdev );
1176     struct xrender_physdev *physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) );
1177
1178     if (!physdev) return FALSE;
1179     physdev->x11dev = x11dev;
1180     physdev->cache_index = -1;
1181     physdev->format = format;
1182     physdev->pict_format = pict_formats[format];
1183     push_dc_driver( pdev, &physdev->dev, &xrender_funcs );
1184     return TRUE;
1185 }
1186
1187 /* store the color mask data in the bitmap info structure */
1188 static void set_color_info( XRenderPictFormat *format, BITMAPINFO *info )
1189 {
1190     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1191
1192     info->bmiHeader.biPlanes      = 1;
1193     info->bmiHeader.biBitCount    = pixmap_formats[format->depth]->bits_per_pixel;
1194     info->bmiHeader.biCompression = BI_RGB;
1195     info->bmiHeader.biClrUsed     = 0;
1196
1197     switch (info->bmiHeader.biBitCount)
1198     {
1199     case 16:
1200         colors[0] = format->direct.redMask   << format->direct.red;
1201         colors[1] = format->direct.greenMask << format->direct.green;
1202         colors[2] = format->direct.blueMask  << format->direct.blue;
1203         info->bmiHeader.biCompression = BI_BITFIELDS;
1204         break;
1205     case 32:
1206         colors[0] = format->direct.redMask   << format->direct.red;
1207         colors[1] = format->direct.greenMask << format->direct.green;
1208         colors[2] = format->direct.blueMask  << format->direct.blue;
1209         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
1210             info->bmiHeader.biCompression = BI_BITFIELDS;
1211         break;
1212     }
1213 }
1214
1215
1216 /**********************************************************************
1217  *           xrenderdrv_CreateDC
1218  */
1219 static BOOL xrenderdrv_CreateDC( PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
1220                                  LPCWSTR output, const DEVMODEW* initData )
1221 {
1222     return create_xrender_dc( pdev, default_format );
1223 }
1224
1225 /**********************************************************************
1226  *           xrenderdrv_CreateCompatibleDC
1227  */
1228 static BOOL xrenderdrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
1229 {
1230     if (orig)  /* chain to x11drv first */
1231     {
1232         orig = GET_NEXT_PHYSDEV( orig, pCreateCompatibleDC );
1233         if (!orig->funcs->pCreateCompatibleDC( orig, pdev )) return FALSE;
1234     }
1235     /* otherwise we have been called by x11drv */
1236
1237     return create_xrender_dc( pdev, WXR_FORMAT_MONO );
1238 }
1239
1240 /**********************************************************************
1241  *           xrenderdrv_DeleteDC
1242  */
1243 static BOOL xrenderdrv_DeleteDC( PHYSDEV dev )
1244 {
1245     struct xrender_physdev *physdev = get_xrender_dev( dev );
1246
1247     free_xrender_picture( physdev );
1248
1249     EnterCriticalSection( &xrender_cs );
1250     if (physdev->cache_index != -1) dec_ref_cache( physdev->cache_index );
1251     LeaveCriticalSection( &xrender_cs );
1252
1253     HeapFree( GetProcessHeap(), 0, physdev );
1254     return TRUE;
1255 }
1256
1257 /**********************************************************************
1258  *           xrenderdrv_ExtEscape
1259  */
1260 static INT xrenderdrv_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data,
1261                                  INT out_count, LPVOID out_data )
1262 {
1263     struct xrender_physdev *physdev = get_xrender_dev( dev );
1264
1265     dev = GET_NEXT_PHYSDEV( dev, pExtEscape );
1266
1267     if (escape == X11DRV_ESCAPE && in_data && in_count >= sizeof(enum x11drv_escape_codes))
1268     {
1269         if (*(const enum x11drv_escape_codes *)in_data == X11DRV_SET_DRAWABLE)
1270         {
1271             BOOL ret = dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1272             if (ret) free_xrender_picture( physdev );  /* pict format doesn't change, only drawable */
1273             return ret;
1274         }
1275     }
1276     return dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1277 }
1278
1279 /****************************************************************************
1280  *        xrenderdrv_CopyBitmap
1281  */
1282 static BOOL xrenderdrv_CopyBitmap( HBITMAP src, HBITMAP dst )
1283 {
1284     return X11DRV_CopyBitmap( src, dst );
1285 }
1286
1287 /****************************************************************************
1288  *        xrenderdrv_CreateBitmap
1289  */
1290 static BOOL xrenderdrv_CreateBitmap( PHYSDEV dev, HBITMAP hbitmap )
1291 {
1292     enum wxr_format format;
1293     BITMAP bitmap;
1294
1295     if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return FALSE;
1296
1297     if (bitmap.bmPlanes != 1) return FALSE;
1298     format = get_bitmap_format( bitmap.bmBitsPixel );
1299
1300     if (pict_formats[format])
1301         return X11DRV_create_phys_bitmap( hbitmap, &bitmap, pict_formats[format]->depth,
1302                                           TRUE, &wxr_color_shifts[format] );
1303
1304     dev = GET_NEXT_PHYSDEV( dev, pCreateBitmap );
1305     return dev->funcs->pCreateBitmap( dev, hbitmap );
1306 }
1307
1308 /****************************************************************************
1309  *        xrenderdrv_DeleteBitmap
1310  */
1311 static BOOL xrenderdrv_DeleteBitmap( HBITMAP hbitmap )
1312 {
1313     return X11DRV_DeleteBitmap( hbitmap );
1314 }
1315
1316 /***********************************************************************
1317  *           xrenderdrv_SelectBitmap
1318  */
1319 static HBITMAP xrenderdrv_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
1320 {
1321     HBITMAP ret;
1322     struct xrender_physdev *physdev = get_xrender_dev( dev );
1323
1324     dev = GET_NEXT_PHYSDEV( dev, pSelectBitmap );
1325     ret = dev->funcs->pSelectBitmap( dev, hbitmap );
1326     if (ret)
1327     {
1328         free_xrender_picture( physdev );
1329         physdev->format = get_xrender_format_from_color_shifts( physdev->x11dev->depth,
1330                                                                 physdev->x11dev->color_shifts );
1331         physdev->pict_format = pict_formats[physdev->format];
1332     }
1333     return ret;
1334 }
1335
1336 /***********************************************************************
1337  *           xrenderdrv_GetImage
1338  */
1339 static DWORD xrenderdrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1340                                   struct gdi_image_bits *bits, struct bitblt_coords *src )
1341 {
1342     if (hbitmap) return X11DRV_GetImage( dev, hbitmap, info, bits, src );
1343     dev = GET_NEXT_PHYSDEV( dev, pGetImage );
1344     return dev->funcs->pGetImage( dev, hbitmap, info, bits, src );
1345 }
1346
1347 /***********************************************************************
1348  *           xrenderdrv_SetDeviceClipping
1349  */
1350 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev, HRGN vis_rgn, HRGN clip_rgn )
1351 {
1352     struct xrender_physdev *physdev = get_xrender_dev( dev );
1353
1354     physdev->update_clip = TRUE;
1355
1356     dev = GET_NEXT_PHYSDEV( dev, pSetDeviceClipping );
1357     dev->funcs->pSetDeviceClipping( dev, vis_rgn, clip_rgn );
1358 }
1359
1360
1361 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
1362 {
1363     XRenderPictFormat *pict_format;
1364     ColorShifts shifts;
1365     const DWORD *bitfields;
1366     static const DWORD bitfields_32[3] = {0xff0000, 0x00ff00, 0x0000ff};
1367     static const DWORD bitfields_16[3] = {0x7c00, 0x03e0, 0x001f};
1368
1369
1370     /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1371      * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1372      * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1373     if (!X11DRV_XRender_Installed || bits_pixel <= 8)
1374         return FALSE;
1375
1376     if(dib->dsBmih.biCompression == BI_BITFIELDS)
1377         bitfields = dib->dsBitfields;
1378     else if(bits_pixel == 24 || bits_pixel == 32)
1379         bitfields = bitfields_32;
1380     else
1381         bitfields = bitfields_16;
1382
1383     X11DRV_PALETTE_ComputeColorShifts(&shifts, bitfields[0], bitfields[1], bitfields[2]);
1384     pict_format = pict_formats[get_xrender_format_from_color_shifts(dib->dsBm.bmBitsPixel, &shifts)];
1385
1386     /* Common formats should be in our picture format table. */
1387     if (!pict_format)
1388     {
1389         TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1390               dib->dsBm.bmBitsPixel, bitfields[0], bitfields[1], bitfields[2]);
1391         return FALSE;
1392     }
1393
1394     physBitmap->depth = pict_format->depth;
1395     physBitmap->trueColor = TRUE;
1396     physBitmap->color_shifts = shifts;
1397     return TRUE;
1398 }
1399
1400 /************************************************************************
1401  *   UploadGlyph
1402  *
1403  * Helper to ExtTextOut.  Must be called inside xrender_cs
1404  */
1405 static void UploadGlyph(struct xrender_physdev *physDev, int glyph, AA_Type format)
1406 {
1407     unsigned int buflen;
1408     char *buf;
1409     Glyph gid;
1410     GLYPHMETRICS gm;
1411     XGlyphInfo gi;
1412     gsCacheEntry *entry = glyphsetCache + physDev->cache_index;
1413     gsCacheEntryFormat *formatEntry;
1414     UINT ggo_format = GGO_GLYPH_INDEX;
1415     enum wxr_format wxr_format;
1416     static const char zero[4];
1417     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1418
1419     switch(format) {
1420     case AA_Grey:
1421         ggo_format |= WINE_GGO_GRAY16_BITMAP;
1422         break;
1423     case AA_RGB:
1424         ggo_format |= WINE_GGO_HRGB_BITMAP;
1425         break;
1426     case AA_BGR:
1427         ggo_format |= WINE_GGO_HBGR_BITMAP;
1428         break;
1429     case AA_VRGB:
1430         ggo_format |= WINE_GGO_VRGB_BITMAP;
1431         break;
1432     case AA_VBGR:
1433         ggo_format |= WINE_GGO_VBGR_BITMAP;
1434         break;
1435
1436     default:
1437         ERR("aa = %d - not implemented\n", format);
1438     case AA_None:
1439         ggo_format |= GGO_BITMAP;
1440         break;
1441     }
1442
1443     buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1444     if(buflen == GDI_ERROR) {
1445         if(format != AA_None) {
1446             format = AA_None;
1447             entry->aa_default = AA_None;
1448             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1449             buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1450         }
1451         if(buflen == GDI_ERROR) {
1452             WARN("GetGlyphOutlineW failed using default glyph\n");
1453             buflen = GetGlyphOutlineW(physDev->dev.hdc, 0, ggo_format, &gm, 0, NULL, &identity);
1454             if(buflen == GDI_ERROR) {
1455                 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1456                 buflen = GetGlyphOutlineW(physDev->dev.hdc, 0x20, ggo_format, &gm, 0, NULL, &identity);
1457                 if(buflen == GDI_ERROR) {
1458                     ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1459                     return;
1460                 }
1461             }
1462         }
1463         TRACE("Turning off antialiasing for this monochrome font\n");
1464     }
1465
1466     /* If there is nothing for the current type, we create the entry. */
1467     if( !entry->format[format] ) {
1468         entry->format[format] = HeapAlloc(GetProcessHeap(),
1469                                           HEAP_ZERO_MEMORY,
1470                                           sizeof(gsCacheEntryFormat));
1471     }
1472     formatEntry = entry->format[format];
1473
1474     if(formatEntry->nrealized <= glyph) {
1475         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1476
1477         if (formatEntry->realized)
1478             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1479                                       HEAP_ZERO_MEMORY,
1480                                       formatEntry->realized,
1481                                       formatEntry->nrealized * sizeof(BOOL));
1482         else
1483             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1484                                       HEAP_ZERO_MEMORY,
1485                                       formatEntry->nrealized * sizeof(BOOL));
1486
1487         if(!X11DRV_XRender_Installed) {
1488           if (formatEntry->bitmaps)
1489             formatEntry->bitmaps = HeapReAlloc(GetProcessHeap(),
1490                                       HEAP_ZERO_MEMORY,
1491                                       formatEntry->bitmaps,
1492                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1493           else
1494             formatEntry->bitmaps = HeapAlloc(GetProcessHeap(),
1495                                       HEAP_ZERO_MEMORY,
1496                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1497         }
1498         if (formatEntry->gis)
1499             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1500                                    HEAP_ZERO_MEMORY,
1501                                    formatEntry->gis,
1502                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1503         else
1504             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1505                                    HEAP_ZERO_MEMORY,
1506                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1507     }
1508
1509
1510     if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
1511         switch(format) {
1512             case AA_Grey:
1513                 wxr_format = WXR_FORMAT_GRAY;
1514                 break;
1515
1516             case AA_RGB:
1517             case AA_BGR:
1518             case AA_VRGB:
1519             case AA_VBGR:
1520                 wxr_format = WXR_FORMAT_A8R8G8B8;
1521                 break;
1522
1523             default:
1524                 ERR("aa = %d - not implemented\n", format);
1525             case AA_None:
1526                 wxr_format = WXR_FORMAT_MONO;
1527                 break;
1528         }
1529
1530         wine_tsx11_lock();
1531         formatEntry->font_format = pict_formats[wxr_format];
1532         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format);
1533         wine_tsx11_unlock();
1534     }
1535
1536
1537     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1538     GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1539     formatEntry->realized[glyph] = TRUE;
1540
1541     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1542           buflen,
1543           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1544           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1545
1546     gi.width = gm.gmBlackBoxX;
1547     gi.height = gm.gmBlackBoxY;
1548     gi.x = -gm.gmptGlyphOrigin.x;
1549     gi.y = gm.gmptGlyphOrigin.y;
1550     gi.xOff = gm.gmCellIncX;
1551     gi.yOff = gm.gmCellIncY;
1552
1553     if(TRACE_ON(xrender)) {
1554         int pitch, i, j;
1555         char output[300];
1556         unsigned char *line;
1557
1558         if(format == AA_None) {
1559             pitch = ((gi.width + 31) / 32) * 4;
1560             for(i = 0; i < gi.height; i++) {
1561                 line = (unsigned char*) buf + i * pitch;
1562                 output[0] = '\0';
1563                 for(j = 0; j < pitch * 8; j++) {
1564                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1565                 }
1566                 TRACE("%s\n", output);
1567             }
1568         } else {
1569             static const char blks[] = " .:;!o*#";
1570             char str[2];
1571
1572             str[1] = '\0';
1573             pitch = ((gi.width + 3) / 4) * 4;
1574             for(i = 0; i < gi.height; i++) {
1575                 line = (unsigned char*) buf + i * pitch;
1576                 output[0] = '\0';
1577                 for(j = 0; j < pitch; j++) {
1578                     str[0] = blks[line[j] >> 5];
1579                     strcat(output, str);
1580                 }
1581                 TRACE("%s\n", output);
1582             }
1583         }
1584     }
1585
1586
1587     if(formatEntry->glyphset) {
1588         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1589             unsigned char *byte = (unsigned char*) buf, c;
1590             int i = buflen;
1591
1592             while(i--) {
1593                 c = *byte;
1594
1595                 /* magic to flip bit order */
1596                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1597                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1598                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1599
1600                 *byte++ = c;
1601             }
1602         }
1603         else if ( format != AA_Grey &&
1604                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1605         {
1606             unsigned int i, *data = (unsigned int *)buf;
1607             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1608         }
1609         gid = glyph;
1610
1611         /*
1612           XRenderCompositeText seems to ignore 0x0 glyphs when
1613           AA_None, which means we lose the advance width of glyphs
1614           like the space.  We'll pretend that such glyphs are 1x1
1615           bitmaps.
1616         */
1617
1618         if(buflen == 0)
1619             gi.width = gi.height = 1;
1620
1621         wine_tsx11_lock();
1622         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1623                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1624         wine_tsx11_unlock();
1625         HeapFree(GetProcessHeap(), 0, buf);
1626     } else {
1627         formatEntry->bitmaps[glyph] = buf;
1628     }
1629
1630     formatEntry->gis[glyph] = gi;
1631 }
1632
1633 static void SharpGlyphMono(struct xrender_physdev *physDev, INT x, INT y,
1634                             void *bitmap, XGlyphInfo *gi)
1635 {
1636     unsigned char   *srcLine = bitmap, *src;
1637     unsigned char   bits, bitsMask;
1638     int             width = gi->width;
1639     int             stride = ((width + 31) & ~31) >> 3;
1640     int             height = gi->height;
1641     int             w;
1642     int             xspan, lenspan;
1643
1644     TRACE("%d, %d\n", x, y);
1645     x -= gi->x;
1646     y -= gi->y;
1647     while (height--)
1648     {
1649         src = srcLine;
1650         srcLine += stride;
1651         w = width;
1652         
1653         bitsMask = 0x80;    /* FreeType is always MSB first */
1654         bits = *src++;
1655         
1656         xspan = x;
1657         while (w)
1658         {
1659             if (bits & bitsMask)
1660             {
1661                 lenspan = 0;
1662                 do
1663                 {
1664                     lenspan++;
1665                     if (lenspan == w)
1666                         break;
1667                     bitsMask = bitsMask >> 1;
1668                     if (!bitsMask)
1669                     {
1670                         bits = *src++;
1671                         bitsMask = 0x80;
1672                     }
1673                 } while (bits & bitsMask);
1674                 XFillRectangle (gdi_display, physDev->x11dev->drawable,
1675                                 physDev->x11dev->gc, xspan, y, lenspan, 1);
1676                 xspan += lenspan;
1677                 w -= lenspan;
1678             }
1679             else
1680             {
1681                 do
1682                 {
1683                     w--;
1684                     xspan++;
1685                     if (!w)
1686                         break;
1687                     bitsMask = bitsMask >> 1;
1688                     if (!bitsMask)
1689                     {
1690                         bits = *src++;
1691                         bitsMask = 0x80;
1692                     }
1693                 } while (!(bits & bitsMask));
1694             }
1695         }
1696         y++;
1697     }
1698 }
1699
1700 static void SharpGlyphGray(struct xrender_physdev *physDev, INT x, INT y,
1701                             void *bitmap, XGlyphInfo *gi)
1702 {
1703     unsigned char   *srcLine = bitmap, *src, bits;
1704     int             width = gi->width;
1705     int             stride = ((width + 3) & ~3);
1706     int             height = gi->height;
1707     int             w;
1708     int             xspan, lenspan;
1709
1710     x -= gi->x;
1711     y -= gi->y;
1712     while (height--)
1713     {
1714         src = srcLine;
1715         srcLine += stride;
1716         w = width;
1717         
1718         bits = *src++;
1719         xspan = x;
1720         while (w)
1721         {
1722             if (bits >= 0x80)
1723             {
1724                 lenspan = 0;
1725                 do
1726                 {
1727                     lenspan++;
1728                     if (lenspan == w)
1729                         break;
1730                     bits = *src++;
1731                 } while (bits >= 0x80);
1732                 XFillRectangle (gdi_display, physDev->x11dev->drawable,
1733                                 physDev->x11dev->gc, xspan, y, lenspan, 1);
1734                 xspan += lenspan;
1735                 w -= lenspan;
1736             }
1737             else
1738             {
1739                 do
1740                 {
1741                     w--;
1742                     xspan++;
1743                     if (!w)
1744                         break;
1745                     bits = *src++;
1746                 } while (bits < 0x80);
1747             }
1748         }
1749         y++;
1750     }
1751 }
1752
1753
1754 static void ExamineBitfield (DWORD mask, int *shift, int *len)
1755 {
1756     int s, l;
1757
1758     s = 0;
1759     while ((mask & 1) == 0)
1760     {
1761         mask >>= 1;
1762         s++;
1763     }
1764     l = 0;
1765     while ((mask & 1) == 1)
1766     {
1767         mask >>= 1;
1768         l++;
1769     }
1770     *shift = s;
1771     *len = l;
1772 }
1773
1774 static DWORD GetField (DWORD pixel, int shift, int len)
1775 {
1776     pixel = pixel & (((1 << (len)) - 1) << shift);
1777     pixel = pixel << (32 - (shift + len)) >> 24;
1778     while (len < 8)
1779     {
1780         pixel |= (pixel >> len);
1781         len <<= 1;
1782     }
1783     return pixel;
1784 }
1785
1786
1787 static DWORD PutField (DWORD pixel, int shift, int len)
1788 {
1789     shift = shift - (8 - len);
1790     if (len <= 8)
1791         pixel &= (((1 << len) - 1) << (8 - len));
1792     if (shift < 0)
1793         pixel >>= -shift;
1794     else
1795         pixel <<= shift;
1796     return pixel;
1797 }
1798
1799 static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInfo *gi,
1800                             int color)
1801 {
1802     int             r_shift, r_len;
1803     int             g_shift, g_len;
1804     int             b_shift, b_len;
1805     BYTE            *maskLine, *mask, m;
1806     int             maskStride;
1807     DWORD           pixel;
1808     int             width, height;
1809     int             w, tx;
1810     BYTE            src_r, src_g, src_b;
1811
1812     x -= gi->x;
1813     y -= gi->y;
1814     width = gi->width;
1815     height = gi->height;
1816
1817     maskLine = bitmap;
1818     maskStride = (width + 3) & ~3;
1819
1820     ExamineBitfield (image->red_mask, &r_shift, &r_len);
1821     ExamineBitfield (image->green_mask, &g_shift, &g_len);
1822     ExamineBitfield (image->blue_mask, &b_shift, &b_len);
1823
1824     src_r = GetField(color, r_shift, r_len);
1825     src_g = GetField(color, g_shift, g_len);
1826     src_b = GetField(color, b_shift, b_len);
1827     
1828     for(; height--; y++)
1829     {
1830         mask = maskLine;
1831         maskLine += maskStride;
1832         w = width;
1833         tx = x;
1834
1835         if(y < 0) continue;
1836         if(y >= image->height) break;
1837
1838         for(; w--; tx++)
1839         {
1840             if(tx >= image->width) break;
1841
1842             m = *mask++;
1843             if(tx < 0) continue;
1844
1845             if (m == 0xff)
1846                 XPutPixel (image, tx, y, color);
1847             else if (m)
1848             {
1849                 BYTE r, g, b;
1850
1851                 pixel = XGetPixel (image, tx, y);
1852
1853                 r = GetField(pixel, r_shift, r_len);
1854                 r = ((BYTE)~m * (WORD)r + (BYTE)m * (WORD)src_r) >> 8;
1855                 g = GetField(pixel, g_shift, g_len);
1856                 g = ((BYTE)~m * (WORD)g + (BYTE)m * (WORD)src_g) >> 8;
1857                 b = GetField(pixel, b_shift, b_len);
1858                 b = ((BYTE)~m * (WORD)b + (BYTE)m * (WORD)src_b) >> 8;
1859
1860                 pixel = (PutField (r, r_shift, r_len) |
1861                          PutField (g, g_shift, g_len) |
1862                          PutField (b, b_shift, b_len));
1863                 XPutPixel (image, tx, y, pixel);
1864             }
1865         }
1866     }
1867 }
1868
1869 /*************************************************************
1870  *                 get_tile_pict
1871  *
1872  * Returns an appropriate Picture for tiling the text colour.
1873  * Call and use result within the xrender_cs
1874  */
1875 static Picture get_tile_pict( enum wxr_format wxr_format, const XRenderColor *color)
1876 {
1877     static struct
1878     {
1879         Pixmap xpm;
1880         Picture pict;
1881         XRenderColor current_color;
1882     } tiles[WXR_NB_FORMATS], *tile;
1883
1884     tile = &tiles[wxr_format];
1885
1886     if(!tile->xpm)
1887     {
1888         XRenderPictureAttributes pa;
1889         XRenderPictFormat *pict_format = pict_formats[wxr_format];
1890
1891         wine_tsx11_lock();
1892         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, pict_format->depth);
1893
1894         pa.repeat = RepeatNormal;
1895         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, pict_format, CPRepeat, &pa);
1896         wine_tsx11_unlock();
1897
1898         /* init current_color to something different from text_pixel */
1899         tile->current_color = *color;
1900         tile->current_color.red ^= 0xffff;
1901
1902         if (wxr_format == WXR_FORMAT_MONO)
1903         {
1904             /* for a 1bpp bitmap we always need a 1 in the tile */
1905             XRenderColor col;
1906             col.red = col.green = col.blue = 0;
1907             col.alpha = 0xffff;
1908             wine_tsx11_lock();
1909             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1910             wine_tsx11_unlock();
1911         }
1912     }
1913
1914     if (memcmp( color, &tile->current_color, sizeof(*color) ) && wxr_format != WXR_FORMAT_MONO)
1915     {
1916         wine_tsx11_lock();
1917         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, color, 0, 0, 1, 1);
1918         wine_tsx11_unlock();
1919         tile->current_color = *color;
1920     }
1921     return tile->pict;
1922 }
1923
1924 /*************************************************************
1925  *                 get_mask_pict
1926  *
1927  * Returns an appropriate Picture for masking with the specified alpha.
1928  * Call and use result within the xrender_cs
1929  */
1930 static Picture get_mask_pict( int alpha )
1931 {
1932     static Pixmap pixmap;
1933     static Picture pict;
1934     static int current_alpha;
1935
1936     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1937
1938     if (!pixmap)
1939     {
1940         XRenderPictureAttributes pa;
1941
1942         wine_tsx11_lock();
1943         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1944         pa.repeat = RepeatNormal;
1945         pict = pXRenderCreatePicture( gdi_display, pixmap,
1946                                       pict_formats[WXR_FORMAT_A8R8G8B8], CPRepeat, &pa );
1947         wine_tsx11_unlock();
1948         current_alpha = -1;
1949     }
1950
1951     if (alpha != current_alpha)
1952     {
1953         XRenderColor col;
1954         col.red = col.green = col.blue = 0;
1955         col.alpha = current_alpha = alpha;
1956         wine_tsx11_lock();
1957         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1958         wine_tsx11_unlock();
1959     }
1960     return pict;
1961 }
1962
1963 static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
1964 {
1965     return 1;
1966 }
1967
1968 /***********************************************************************
1969  *           xrenderdrv_ExtTextOut
1970  */
1971 static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
1972                                    const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx )
1973 {
1974     struct xrender_physdev *physdev = get_xrender_dev( dev );
1975     XGCValues xgcval;
1976     gsCacheEntry *entry;
1977     gsCacheEntryFormat *formatEntry;
1978     BOOL retv = FALSE;
1979     int textPixel, backgroundPixel;
1980     RGNDATA *saved_region = NULL;
1981     AA_Type aa_type = AA_None;
1982     unsigned int idx;
1983     Picture tile_pict = 0;
1984
1985     if (!physdev->x11dev->has_gdi_font)
1986     {
1987         dev = GET_NEXT_PHYSDEV( dev, pExtTextOut );
1988         return dev->funcs->pExtTextOut( dev, x, y, flags, lprect, wstr, count, lpDx );
1989     }
1990
1991     xgcval.function = GXcopy;
1992     xgcval.background = physdev->x11dev->backgroundPixel;
1993     xgcval.fill_style = FillSolid;
1994     wine_tsx11_lock();
1995     XChangeGC( gdi_display, physdev->x11dev->gc, GCFunction | GCBackground | GCFillStyle, &xgcval );
1996     wine_tsx11_unlock();
1997
1998     X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
1999
2000     if(physdev->x11dev->depth == 1) {
2001         if((physdev->x11dev->textPixel & 0xffffff) == 0) {
2002             textPixel = 0;
2003             backgroundPixel = 1;
2004         } else {
2005             textPixel = 1;
2006             backgroundPixel = 0;
2007         }
2008     } else {
2009         textPixel = physdev->x11dev->textPixel;
2010         backgroundPixel = physdev->x11dev->backgroundPixel;
2011     }
2012
2013     if(flags & ETO_OPAQUE)
2014     {
2015         wine_tsx11_lock();
2016         XSetForeground( gdi_display, physdev->x11dev->gc, backgroundPixel );
2017         XFillRectangle( gdi_display, physdev->x11dev->drawable, physdev->x11dev->gc,
2018                         physdev->x11dev->dc_rect.left + lprect->left, physdev->x11dev->dc_rect.top + lprect->top,
2019                         lprect->right - lprect->left, lprect->bottom - lprect->top );
2020         wine_tsx11_unlock();
2021     }
2022
2023     if(count == 0)
2024     {
2025         retv = TRUE;
2026         goto done_unlock;
2027     }
2028
2029     EnterCriticalSection(&xrender_cs);
2030
2031     entry = glyphsetCache + physdev->cache_index;
2032     aa_type = entry->aa_default;
2033     formatEntry = entry->format[aa_type];
2034
2035     for(idx = 0; idx < count; idx++) {
2036         if( !formatEntry ) {
2037             UploadGlyph(physdev, wstr[idx], aa_type);
2038             /* re-evaluate antialias since aa_default may have changed */
2039             aa_type = entry->aa_default;
2040             formatEntry = entry->format[aa_type];
2041         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
2042             UploadGlyph(physdev, wstr[idx], aa_type);
2043         }
2044     }
2045     if (!formatEntry)
2046     {
2047         WARN("could not upload requested glyphs\n");
2048         LeaveCriticalSection(&xrender_cs);
2049         goto done_unlock;
2050     }
2051
2052     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
2053           physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
2054
2055     if(X11DRV_XRender_Installed)
2056     {
2057         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
2058         POINT offset = {0, 0};
2059         POINT desired, current;
2060         int render_op = PictOpOver;
2061         Picture pict = get_xrender_picture( physdev, 0, (flags & ETO_CLIPPED) ? lprect : NULL );
2062         XRenderColor col;
2063
2064         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
2065            So we pass zeros to the function and move to our starting position using the first
2066            element of the elts array. */
2067
2068         desired.x = physdev->x11dev->dc_rect.left + x;
2069         desired.y = physdev->x11dev->dc_rect.top + y;
2070         current.x = current.y = 0;
2071
2072         get_xrender_color(physdev->pict_format, physdev->x11dev->textPixel, &col);
2073         tile_pict = get_tile_pict(physdev->format, &col);
2074
2075         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
2076          */
2077         if((physdev->format == WXR_FORMAT_MONO) && (textPixel == 0))
2078             render_op = PictOpOutReverse; /* This gives us 'black' text */
2079
2080         for(idx = 0; idx < count; idx++)
2081         {
2082             elts[idx].glyphset = formatEntry->glyphset;
2083             elts[idx].chars = wstr + idx;
2084             elts[idx].nchars = 1;
2085             elts[idx].xOff = desired.x - current.x;
2086             elts[idx].yOff = desired.y - current.y;
2087
2088             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
2089             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
2090
2091             if(!lpDx)
2092             {
2093                 desired.x += formatEntry->gis[wstr[idx]].xOff;
2094                 desired.y += formatEntry->gis[wstr[idx]].yOff;
2095             }
2096             else
2097             {
2098                 if(flags & ETO_PDY)
2099                 {
2100                     offset.x += lpDx[idx * 2];
2101                     offset.y += lpDx[idx * 2 + 1];
2102                 }
2103                 else
2104                     offset.x += lpDx[idx];
2105                 desired.x = physdev->x11dev->dc_rect.left + x + offset.x;
2106                 desired.y = physdev->x11dev->dc_rect.top  + y + offset.y;
2107             }
2108         }
2109
2110         wine_tsx11_lock();
2111         /* Make sure we don't have any transforms set from a previous call */
2112         set_xrender_transformation(pict, 1, 1, 0, 0);
2113         pXRenderCompositeText16(gdi_display, render_op,
2114                                 tile_pict,
2115                                 pict,
2116                                 formatEntry->font_format,
2117                                 0, 0, 0, 0, elts, count);
2118         wine_tsx11_unlock();
2119         HeapFree(GetProcessHeap(), 0, elts);
2120     } else {
2121         POINT offset = {0, 0};
2122
2123         if (flags & ETO_CLIPPED)
2124         {
2125             HRGN clip_region = CreateRectRgnIndirect( lprect );
2126             saved_region = add_extra_clipping_region( physdev->x11dev, clip_region );
2127             DeleteObject( clip_region );
2128         }
2129
2130         wine_tsx11_lock();
2131         XSetForeground( gdi_display, physdev->x11dev->gc, textPixel );
2132
2133         if(aa_type == AA_None || physdev->x11dev->depth == 1)
2134         {
2135             void (* sharp_glyph_fn)(struct xrender_physdev *, INT, INT, void *, XGlyphInfo *);
2136
2137             if(aa_type == AA_None)
2138                 sharp_glyph_fn = SharpGlyphMono;
2139             else
2140                 sharp_glyph_fn = SharpGlyphGray;
2141
2142             for(idx = 0; idx < count; idx++) {
2143                 sharp_glyph_fn(physdev,
2144                                physdev->x11dev->dc_rect.left + x + offset.x,
2145                                physdev->x11dev->dc_rect.top  + y + offset.y,
2146                                formatEntry->bitmaps[wstr[idx]],
2147                                &formatEntry->gis[wstr[idx]]);
2148                 if(lpDx)
2149                 {
2150                     if(flags & ETO_PDY)
2151                     {
2152                         offset.x += lpDx[idx * 2];
2153                         offset.y += lpDx[idx * 2 + 1];
2154                     }
2155                     else
2156                         offset.x += lpDx[idx];
2157                 }
2158                 else
2159                 {
2160                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2161                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2162                 }
2163             }
2164         } else {
2165             XImage *image;
2166             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
2167             RECT extents = {0, 0, 0, 0};
2168             POINT cur = {0, 0};
2169             int w = physdev->x11dev->drawable_rect.right - physdev->x11dev->drawable_rect.left;
2170             int h = physdev->x11dev->drawable_rect.bottom - physdev->x11dev->drawable_rect.top;
2171
2172             TRACE("drawable %dx%d\n", w, h);
2173
2174             for(idx = 0; idx < count; idx++) {
2175                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
2176                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
2177                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
2178                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
2179                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
2180                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
2181                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
2182                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
2183
2184                 if(lpDx)
2185                 {
2186                     if(flags & ETO_PDY)
2187                     {
2188                         cur.x += lpDx[idx * 2];
2189                         cur.y += lpDx[idx * 2 + 1];
2190                     }
2191                     else
2192                         cur.x += lpDx[idx];
2193                 }
2194                 else
2195                 {
2196                     cur.x += formatEntry->gis[wstr[idx]].xOff;
2197                     cur.y += formatEntry->gis[wstr[idx]].yOff;
2198                 }
2199             }
2200             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
2201                   extents.right, extents.bottom, physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
2202
2203             if(physdev->x11dev->dc_rect.left + x + extents.left >= 0) {
2204                 image_x = physdev->x11dev->dc_rect.left + x + extents.left;
2205                 image_off_x = 0;
2206             } else {
2207                 image_x = 0;
2208                 image_off_x = physdev->x11dev->dc_rect.left + x + extents.left;
2209             }
2210             if(physdev->x11dev->dc_rect.top + y + extents.top >= 0) {
2211                 image_y = physdev->x11dev->dc_rect.top + y + extents.top;
2212                 image_off_y = 0;
2213             } else {
2214                 image_y = 0;
2215                 image_off_y = physdev->x11dev->dc_rect.top + y + extents.top;
2216             }
2217             if(physdev->x11dev->dc_rect.left + x + extents.right < w)
2218                 image_w = physdev->x11dev->dc_rect.left + x + extents.right - image_x;
2219             else
2220                 image_w = w - image_x;
2221             if(physdev->x11dev->dc_rect.top + y + extents.bottom < h)
2222                 image_h = physdev->x11dev->dc_rect.top + y + extents.bottom - image_y;
2223             else
2224                 image_h = h - image_y;
2225
2226             if(image_w <= 0 || image_h <= 0) goto no_image;
2227
2228             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2229             image = XGetImage(gdi_display, physdev->x11dev->drawable,
2230                               image_x, image_y, image_w, image_h,
2231                               AllPlanes, ZPixmap);
2232             X11DRV_check_error();
2233
2234             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2235                   gdi_display, (int)physdev->x11dev->drawable, image_x, image_y,
2236                   image_w, image_h, AllPlanes, ZPixmap,
2237                   physdev->x11dev->depth, image);
2238             if(!image) {
2239                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
2240                                            physdev->x11dev->depth);
2241                 GC gc;
2242                 XGCValues gcv;
2243
2244                 gcv.graphics_exposures = False;
2245                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
2246                 XCopyArea(gdi_display, physdev->x11dev->drawable, xpm, gc, image_x, image_y,
2247                           image_w, image_h, 0, 0);
2248                 XFreeGC(gdi_display, gc);
2249                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2250                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
2251                                   ZPixmap);
2252                 X11DRV_check_error();
2253                 XFreePixmap(gdi_display, xpm);
2254             }
2255             if(!image) goto no_image;
2256
2257             image->red_mask = visual->red_mask;
2258             image->green_mask = visual->green_mask;
2259             image->blue_mask = visual->blue_mask;
2260
2261             for(idx = 0; idx < count; idx++) {
2262                 SmoothGlyphGray(image,
2263                                 offset.x + image_off_x - extents.left,
2264                                 offset.y + image_off_y - extents.top,
2265                                 formatEntry->bitmaps[wstr[idx]],
2266                                 &formatEntry->gis[wstr[idx]],
2267                                 physdev->x11dev->textPixel);
2268                 if(lpDx)
2269                 {
2270                     if(flags & ETO_PDY)
2271                     {
2272                         offset.x += lpDx[idx * 2];
2273                         offset.y += lpDx[idx * 2 + 1];
2274                     }
2275                     else
2276                         offset.x += lpDx[idx];
2277                 }
2278                 else
2279                 {
2280                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2281                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2282                 }
2283             }
2284             XPutImage(gdi_display, physdev->x11dev->drawable, physdev->x11dev->gc, image, 0, 0,
2285                       image_x, image_y, image_w, image_h);
2286             XDestroyImage(image);
2287         }
2288     no_image:
2289         wine_tsx11_unlock();
2290         restore_clipping_region( physdev->x11dev, saved_region );
2291     }
2292     LeaveCriticalSection(&xrender_cs);
2293     retv = TRUE;
2294
2295 done_unlock:
2296     X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2297     return retv;
2298 }
2299
2300 /* multiply the alpha channel of a picture */
2301 static void multiply_alpha( Picture pict, XRenderPictFormat *format, int alpha,
2302                             int x, int y, int width, int height )
2303 {
2304     XRenderPictureAttributes pa;
2305     Pixmap src_pixmap, mask_pixmap;
2306     Picture src_pict, mask_pict;
2307     XRenderColor color;
2308
2309     wine_tsx11_lock();
2310     src_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
2311     mask_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
2312     pa.repeat = RepeatNormal;
2313     src_pict = pXRenderCreatePicture( gdi_display, src_pixmap, format, CPRepeat, &pa );
2314     pa.component_alpha = True;
2315     mask_pict = pXRenderCreatePicture( gdi_display, mask_pixmap, format, CPRepeat|CPComponentAlpha, &pa );
2316     color.red = color.green = color.blue = color.alpha = 0xffff;
2317     pXRenderFillRectangle( gdi_display, PictOpSrc, src_pict, &color, 0, 0, 1, 1 );
2318     color.alpha = alpha;
2319     pXRenderFillRectangle( gdi_display, PictOpSrc, mask_pict, &color, 0, 0, 1, 1 );
2320     pXRenderComposite( gdi_display, PictOpInReverse, src_pict, mask_pict, pict,
2321                        0, 0, 0, 0, x, y, width, height );
2322     pXRenderFreePicture( gdi_display, src_pict );
2323     pXRenderFreePicture( gdi_display, mask_pict );
2324     XFreePixmap( gdi_display, src_pixmap );
2325     XFreePixmap( gdi_display, mask_pixmap );
2326     wine_tsx11_unlock();
2327 }
2328
2329 /* Helper function for (stretched) blitting using xrender */
2330 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
2331                           int x_src, int y_src, int x_dst, int y_dst,
2332                           double xscale, double yscale, int width, int height )
2333 {
2334     int x_offset, y_offset;
2335
2336     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2337      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2338      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2339     wine_tsx11_lock();
2340     if(xscale != 1.0 || yscale != 1.0)
2341     {
2342         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2343          * in the wrong quadrant of the x-y plane.
2344          */
2345         x_offset = (xscale < 0) ? -width : 0;
2346         y_offset = (yscale < 0) ? -height : 0;
2347         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2348     }
2349     else
2350     {
2351         x_offset = x_src;
2352         y_offset = y_src;
2353         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2354     }
2355     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
2356                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
2357     wine_tsx11_unlock();
2358 }
2359
2360 /* Helper function for (stretched) mono->color blitting using xrender */
2361 static void xrender_mono_blit( Picture src_pict, Picture dst_pict,
2362                                enum wxr_format dst_format, XRenderColor *fg, XRenderColor *bg,
2363                                int x_src, int y_src, int x_dst, int y_dst,
2364                                double xscale, double yscale, int width, int height )
2365 {
2366     Picture tile_pict;
2367     int x_offset, y_offset;
2368     XRenderColor color;
2369
2370     /* When doing a mono->color blit, the source data is used as mask, and the source picture
2371      * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
2372      * the tile data.
2373      */
2374     EnterCriticalSection( &xrender_cs );
2375     color = *bg;
2376     color.alpha = 0xffff;  /* tile pict needs 100% alpha */
2377     tile_pict = get_tile_pict( dst_format, &color );
2378
2379     wine_tsx11_lock();
2380     pXRenderFillRectangle( gdi_display, PictOpSrc, dst_pict, fg, x_dst, y_dst, width, height );
2381
2382     if (xscale != 1.0 || yscale != 1.0)
2383     {
2384         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2385          * in the wrong quadrant of the x-y plane.
2386          */
2387         x_offset = (xscale < 0) ? -width : 0;
2388         y_offset = (yscale < 0) ? -height : 0;
2389         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2390     }
2391     else
2392     {
2393         x_offset = x_src;
2394         y_offset = y_src;
2395         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2396     }
2397     pXRenderComposite(gdi_display, PictOpOver, tile_pict, src_pict, dst_pict,
2398                       0, 0, x_offset, y_offset, x_dst, y_dst, width, height );
2399     wine_tsx11_unlock();
2400     LeaveCriticalSection( &xrender_cs );
2401
2402     /* force the alpha channel for background pixels, it has been set to 100% by the tile */
2403     if (bg->alpha != 0xffff && (dst_format == WXR_FORMAT_A8R8G8B8 || dst_format == WXR_FORMAT_B8G8R8A8))
2404         multiply_alpha( dst_pict, pict_formats[dst_format], bg->alpha, x_dst, y_dst, width, height );
2405 }
2406
2407 /* create a pixmap and render picture for an image */
2408 static DWORD create_image_pixmap( BITMAPINFO *info, const struct gdi_image_bits *bits,
2409                                   struct bitblt_coords *src, enum wxr_format format,
2410                                   Pixmap *pixmap, Picture *pict, BOOL *use_repeat )
2411 {
2412     DWORD ret;
2413     int width = src->visrect.right - src->visrect.left;
2414     int height = src->visrect.bottom - src->visrect.top;
2415     int depth = pict_formats[format]->depth;
2416     struct gdi_image_bits dst_bits;
2417     XRenderPictureAttributes pa;
2418     XImage *image;
2419
2420     wine_tsx11_lock();
2421     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
2422                           info->bmiHeader.biWidth, height, 32, 0 );
2423     wine_tsx11_unlock();
2424     if (!image) return ERROR_OUTOFMEMORY;
2425
2426     ret = copy_image_bits( info, (format == WXR_FORMAT_R8G8B8), image, bits, &dst_bits, src, NULL, ~0u );
2427     if (ret) return ret;
2428
2429     image->data = dst_bits.ptr;
2430     /* hack: make sure the bits are readable if we are reading from a DIB section */
2431     /* to be removed once we get rid of DIB access protections */
2432     if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, image->height * image->bytes_per_line );
2433
2434     *use_repeat = (width == 1 && height == 1);
2435     pa.repeat = *use_repeat ? RepeatNormal : RepeatNone;
2436
2437     wine_tsx11_lock();
2438     *pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
2439     XPutImage( gdi_display, *pixmap, get_bitmap_gc( depth ), image,
2440                src->visrect.left, 0, 0, 0, width, height );
2441     *pict = pXRenderCreatePicture( gdi_display, *pixmap, pict_formats[format], CPRepeat, &pa );
2442     wine_tsx11_unlock();
2443
2444     /* make coordinates relative to the pixmap */
2445     src->x -= src->visrect.left;
2446     src->y -= src->visrect.top;
2447     OffsetRect( &src->visrect, -src->visrect.left, -src->visrect.top );
2448
2449     image->data = NULL;
2450     wine_tsx11_lock();
2451     XDestroyImage( image );
2452     wine_tsx11_unlock();
2453     if (dst_bits.free) dst_bits.free( &dst_bits );
2454     return ret;
2455 }
2456
2457 static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
2458                                   Drawable drawable, const struct bitblt_coords *src,
2459                                   const struct bitblt_coords *dst )
2460 {
2461     int width = abs( dst->width );
2462     int height = abs( dst->height );
2463     int x_src = physdev_src->x11dev->dc_rect.left + src->x;
2464     int y_src = physdev_src->x11dev->dc_rect.top + src->y;
2465     int x_dst, y_dst;
2466     Picture src_pict = 0, dst_pict, mask_pict = 0;
2467     BOOL use_repeat;
2468     double xscale, yscale;
2469
2470     use_repeat = use_source_repeat( physdev_src );
2471     if (!use_repeat)
2472     {
2473         xscale = src->width / (double)dst->width;
2474         yscale = src->height / (double)dst->height;
2475     }
2476     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2477
2478     if (drawable)  /* using an intermediate pixmap */
2479     {
2480         XRenderPictureAttributes pa;
2481
2482         x_dst = dst->x;
2483         y_dst = dst->y;
2484         pa.repeat = RepeatNone;
2485         wine_tsx11_lock();
2486         dst_pict = pXRenderCreatePicture( gdi_display, drawable, physdev_dst->pict_format, CPRepeat, &pa );
2487         wine_tsx11_unlock();
2488     }
2489     else
2490     {
2491         x_dst = physdev_dst->x11dev->dc_rect.left + dst->x;
2492         y_dst = physdev_dst->x11dev->dc_rect.top + dst->y;
2493         dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
2494     }
2495
2496     if (src->width < 0) x_src += src->width + 1;
2497     if (src->height < 0) y_src += src->height + 1;
2498     if (dst->width < 0) x_dst += dst->width + 1;
2499     if (dst->height < 0) y_dst += dst->height + 1;
2500
2501     src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2502
2503     /* mono -> color */
2504     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2505     {
2506         XRenderColor fg, bg;
2507
2508         get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->textPixel, &fg );
2509         get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->backgroundPixel, &bg );
2510         fg.alpha = bg.alpha = 0;
2511
2512         xrender_mono_blit( src_pict, dst_pict, physdev_dst->format, &fg, &bg,
2513                            x_src, y_src, x_dst, y_dst, xscale, yscale, width, height );
2514     }
2515     else /* color -> color (can be at different depths) or mono -> mono */
2516     {
2517         if (physdev_dst->x11dev->depth == 32 && physdev_src->x11dev->depth < 32)
2518             mask_pict = get_no_alpha_mask();
2519
2520         xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict,
2521                       x_src, y_src, x_dst, y_dst, xscale, yscale, width, height );
2522     }
2523
2524     if (drawable)
2525     {
2526         wine_tsx11_lock();
2527         pXRenderFreePicture( gdi_display, dst_pict );
2528         wine_tsx11_unlock();
2529     }
2530 }
2531
2532
2533 static void xrender_put_image( Pixmap src_pixmap, Picture src_pict, Picture mask_pict, HRGN clip,
2534                                XRenderPictFormat *dst_format, struct xrender_physdev *physdev,
2535                                Drawable drawable, struct bitblt_coords *src,
2536                                struct bitblt_coords *dst, BOOL use_repeat )
2537 {
2538     int x_src, y_src, x_dst, y_dst;
2539     Picture dst_pict;
2540     XRenderPictureAttributes pa;
2541     double xscale, yscale;
2542
2543     if (drawable)  /* using an intermediate pixmap */
2544     {
2545         RGNDATA *clip_data = NULL;
2546
2547         if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
2548         x_dst = dst->x;
2549         y_dst = dst->y;
2550         pa.repeat = RepeatNone;
2551         wine_tsx11_lock();
2552         dst_pict = pXRenderCreatePicture( gdi_display, drawable, dst_format, CPRepeat, &pa );
2553         if (clip_data)
2554             pXRenderSetPictureClipRectangles( gdi_display, dst_pict, 0, 0,
2555                                               (XRectangle *)clip_data->Buffer, clip_data->rdh.nCount );
2556         wine_tsx11_unlock();
2557         HeapFree( GetProcessHeap(), 0, clip_data );
2558     }
2559     else
2560     {
2561         x_dst = physdev->x11dev->dc_rect.left + dst->x;
2562         y_dst = physdev->x11dev->dc_rect.top + dst->y;
2563         dst_pict = get_xrender_picture( physdev, clip, &dst->visrect );
2564     }
2565
2566     if (!use_repeat)
2567     {
2568         xscale = src->width / (double)dst->width;
2569         yscale = src->height / (double)dst->height;
2570     }
2571     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2572
2573     x_src = src->x;
2574     y_src = src->y;
2575     if (src->width < 0) x_src += src->width + 1;
2576     if (src->height < 0) y_src += src->height + 1;
2577     if (dst->width < 0) x_dst += dst->width + 1;
2578     if (dst->height < 0) y_dst += dst->height + 1;
2579
2580     xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict, x_src, y_src, x_dst, y_dst,
2581                   xscale, yscale, abs( dst->width ), abs( dst->height ));
2582
2583     if (drawable)
2584     {
2585         wine_tsx11_lock();
2586         pXRenderFreePicture( gdi_display, dst_pict );
2587         wine_tsx11_unlock();
2588     }
2589 }
2590
2591
2592 /***********************************************************************
2593  *           xrenderdrv_StretchBlt
2594  */
2595 static BOOL xrenderdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
2596                                    PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
2597 {
2598     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2599     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2600     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2601
2602     if (src_dev->funcs != dst_dev->funcs)
2603     {
2604         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
2605         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
2606     }
2607
2608     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2609
2610     /* XRender is of no use for color -> mono */
2611     if (physdev_dst->format == WXR_FORMAT_MONO && physdev_src->format != WXR_FORMAT_MONO)
2612         goto x11drv_fallback;
2613
2614     /* if not stretching, we only need to handle format conversion */
2615     if (!stretch && physdev_dst->format == physdev_src->format) goto x11drv_fallback;
2616
2617     X11DRV_LockDIBSection( physdev_dst->x11dev, DIB_Status_GdiMod );
2618     if (physdev_dst != physdev_src) X11DRV_LockDIBSection( physdev_src->x11dev, DIB_Status_GdiMod );
2619
2620     if (rop != SRCCOPY)
2621     {
2622         GC tmpGC;
2623         Pixmap tmp_pixmap;
2624         struct bitblt_coords tmp;
2625
2626         /* make coordinates relative to tmp pixmap */
2627         tmp = *dst;
2628         tmp.x -= tmp.visrect.left;
2629         tmp.y -= tmp.visrect.top;
2630         OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2631
2632         wine_tsx11_lock();
2633         tmpGC = XCreateGC( gdi_display, physdev_dst->x11dev->drawable, 0, NULL );
2634         XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
2635         XSetGraphicsExposures( gdi_display, tmpGC, False );
2636         tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2637                                     tmp.visrect.bottom - tmp.visrect.top, physdev_dst->x11dev->depth );
2638         wine_tsx11_unlock();
2639
2640         xrender_stretch_blit( physdev_src, physdev_dst, tmp_pixmap, src, &tmp );
2641         execute_rop( physdev_dst->x11dev, tmp_pixmap, tmpGC, &dst->visrect, rop );
2642
2643         wine_tsx11_lock();
2644         XFreePixmap( gdi_display, tmp_pixmap );
2645         XFreeGC( gdi_display, tmpGC );
2646         wine_tsx11_unlock();
2647     }
2648     else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
2649
2650     if (physdev_dst != physdev_src) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2651     X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2652     return TRUE;
2653
2654 x11drv_fallback:
2655     return X11DRV_StretchBlt( &physdev_dst->x11dev->dev, dst, &physdev_src->x11dev->dev, src, rop );
2656 }
2657
2658
2659 /***********************************************************************
2660  *           xrenderdrv_PutImage
2661  */
2662 static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
2663                                   const struct gdi_image_bits *bits, struct bitblt_coords *src,
2664                                   struct bitblt_coords *dst, DWORD rop )
2665 {
2666     struct xrender_physdev *physdev;
2667     X_PHYSBITMAP *bitmap;
2668     DWORD ret;
2669     Pixmap tmp_pixmap;
2670     GC gc;
2671     enum wxr_format src_format, dst_format;
2672     XRenderPictFormat *pict_format;
2673     Pixmap src_pixmap;
2674     Picture src_pict, mask_pict = 0;
2675     BOOL use_repeat;
2676
2677     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2678
2679     if (hbitmap)
2680     {
2681         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
2682         physdev = NULL;
2683         dst_format = get_xrender_format_from_color_shifts( bitmap->depth, &bitmap->color_shifts );
2684     }
2685     else
2686     {
2687         physdev = get_xrender_dev( dev );
2688         bitmap = NULL;
2689         dst_format = physdev->format;
2690     }
2691
2692     src_format = get_xrender_format_from_bitmapinfo( info );
2693     if (!(pict_format = pict_formats[src_format])) goto update_format;
2694
2695     /* make sure we can create an image with the same bpp */
2696     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2697         goto update_format;
2698
2699     /* mono <-> color conversions not supported */
2700     if ((src_format != dst_format) && (src_format == WXR_FORMAT_MONO || dst_format == WXR_FORMAT_MONO))
2701         goto x11drv_fallback;
2702
2703     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2704
2705     if (!has_alpha( src_format ) && has_alpha( dst_format )) mask_pict = get_no_alpha_mask();
2706
2707     ret = create_image_pixmap( info, bits, src, src_format, &src_pixmap, &src_pict, &use_repeat );
2708     if (!ret)
2709     {
2710         struct bitblt_coords tmp;
2711
2712         if (bitmap)
2713         {
2714             HRGN rgn = CreateRectRgnIndirect( &dst->visrect );
2715             if (clip) CombineRgn( rgn, rgn, clip, RGN_AND );
2716
2717             X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
2718
2719             xrender_put_image( src_pixmap, src_pict, mask_pict, rgn,
2720                                pict_formats[dst_format], NULL, bitmap->pixmap, src, dst, use_repeat );
2721
2722             X11DRV_DIB_Unlock( bitmap, TRUE );
2723             DeleteObject( rgn );
2724         }
2725         else
2726         {
2727             X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
2728
2729             if (rop != SRCCOPY)
2730             {
2731                 RGNDATA *clip_data = NULL;
2732
2733                 /* make coordinates relative to tmp pixmap */
2734                 tmp = *dst;
2735                 tmp.x -= tmp.visrect.left;
2736                 tmp.y -= tmp.visrect.top;
2737                 OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2738
2739                 if (clip) clip_data = add_extra_clipping_region( physdev->x11dev, clip );
2740
2741                 wine_tsx11_lock();
2742                 gc = XCreateGC( gdi_display, physdev->x11dev->drawable, 0, NULL );
2743                 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
2744                 XSetGraphicsExposures( gdi_display, gc, False );
2745                 tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2746                                             tmp.visrect.bottom - tmp.visrect.top, physdev->x11dev->depth );
2747                 wine_tsx11_unlock();
2748
2749                 xrender_put_image( src_pixmap, src_pict, mask_pict, NULL, physdev->pict_format,
2750                                    NULL, tmp_pixmap, src, &tmp, use_repeat );
2751                 execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
2752
2753                 wine_tsx11_lock();
2754                 XFreePixmap( gdi_display, tmp_pixmap );
2755                 XFreeGC( gdi_display, gc );
2756                 wine_tsx11_unlock();
2757
2758                 restore_clipping_region( physdev->x11dev, clip_data );
2759             }
2760             else xrender_put_image( src_pixmap, src_pict, mask_pict, clip,
2761                                     physdev->pict_format, physdev, 0, src, dst, use_repeat );
2762
2763             X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2764         }
2765
2766         wine_tsx11_lock();
2767         pXRenderFreePicture( gdi_display, src_pict );
2768         XFreePixmap( gdi_display, src_pixmap );
2769         wine_tsx11_unlock();
2770     }
2771     return ret;
2772
2773 update_format:
2774     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2775     set_color_info( pict_formats[dst_format], info );
2776     return ERROR_BAD_FORMAT;
2777
2778 x11drv_fallback:
2779     if (hbitmap) return X11DRV_PutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
2780     dev = GET_NEXT_PHYSDEV( dev, pPutImage );
2781     return dev->funcs->pPutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
2782 }
2783
2784
2785 /***********************************************************************
2786  *           xrenderdrv_BlendImage
2787  */
2788 static DWORD xrenderdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits,
2789                                     struct bitblt_coords *src, struct bitblt_coords *dst,
2790                                     BLENDFUNCTION func )
2791 {
2792     struct xrender_physdev *physdev = get_xrender_dev( dev );
2793     DWORD ret;
2794     enum wxr_format format;
2795     XRenderPictFormat *pict_format;
2796     Picture dst_pict, src_pict, mask_pict;
2797     Pixmap src_pixmap;
2798     BOOL use_repeat;
2799
2800     if (!X11DRV_XRender_Installed)
2801     {
2802         dev = GET_NEXT_PHYSDEV( dev, pBlendImage );
2803         return dev->funcs->pBlendImage( dev, info, bits, src, dst, func );
2804     }
2805
2806     format = get_xrender_format_from_bitmapinfo( info );
2807     if (!(func.AlphaFormat & AC_SRC_ALPHA))
2808         format = get_format_without_alpha( format );
2809     else if (format != WXR_FORMAT_A8R8G8B8)
2810         return ERROR_INVALID_PARAMETER;
2811
2812     if (!(pict_format = pict_formats[format])) goto update_format;
2813
2814     /* make sure we can create an image with the same bpp */
2815     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2816         goto update_format;
2817
2818     if (format == WXR_FORMAT_MONO && physdev->format != WXR_FORMAT_MONO)
2819         goto update_format;
2820
2821     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2822
2823     ret = create_image_pixmap( info, bits, src, format, &src_pixmap, &src_pict, &use_repeat );
2824     if (!ret)
2825     {
2826         double xscale, yscale;
2827
2828         X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
2829
2830         if (!use_repeat)
2831         {
2832             xscale = src->width / (double)dst->width;
2833             yscale = src->height / (double)dst->height;
2834         }
2835         else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2836
2837         dst_pict = get_xrender_picture( physdev, 0, &dst->visrect );
2838
2839         EnterCriticalSection( &xrender_cs );
2840         mask_pict = get_mask_pict( func.SourceConstantAlpha * 257 );
2841
2842         xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict, src->x, src->y,
2843                       physdev->x11dev->dc_rect.left + dst->x,
2844                       physdev->x11dev->dc_rect.top + dst->y,
2845                       xscale, yscale, dst->width, dst->height );
2846
2847         wine_tsx11_lock();
2848         pXRenderFreePicture( gdi_display, src_pict );
2849         XFreePixmap( gdi_display, src_pixmap );
2850         wine_tsx11_unlock();
2851
2852         LeaveCriticalSection( &xrender_cs );
2853
2854         X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2855     }
2856     return ret;
2857
2858 update_format:
2859     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2860     set_color_info( physdev->pict_format, info );
2861     return ERROR_BAD_FORMAT;
2862 }
2863
2864
2865 /***********************************************************************
2866  *           xrenderdrv_AlphaBlend
2867  */
2868 static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
2869                                    PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2870 {
2871     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2872     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2873     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2874     XRenderPictureAttributes pa;
2875     Pixmap tmp_pixmap = 0;
2876     double xscale, yscale;
2877     BOOL use_repeat;
2878
2879     if (!X11DRV_XRender_Installed || src_dev->funcs != dst_dev->funcs)
2880     {
2881         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pAlphaBlend );
2882         return dst_dev->funcs->pAlphaBlend( dst_dev, dst, src_dev, src, blendfn );
2883     }
2884
2885     if ((blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->format != WXR_FORMAT_A8R8G8B8)
2886     {
2887         SetLastError( ERROR_INVALID_PARAMETER );
2888         return FALSE;
2889     }
2890
2891     X11DRV_LockDIBSection( physdev_dst->x11dev, DIB_Status_GdiMod );
2892     if (physdev_dst != physdev_src) X11DRV_LockDIBSection( physdev_src->x11dev, DIB_Status_GdiMod );
2893
2894     dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
2895
2896     use_repeat = use_source_repeat( physdev_src );
2897     if (!use_repeat)
2898     {
2899         xscale = src->width / (double)dst->width;
2900         yscale = src->height / (double)dst->height;
2901     }
2902     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2903
2904     src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2905
2906     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2907     {
2908         /* mono -> color blending needs an intermediate color pixmap */
2909         XRenderColor fg, bg;
2910         int width = src->visrect.right - src->visrect.left;
2911         int height = src->visrect.bottom - src->visrect.top;
2912
2913         /* blending doesn't use the destination DC colors */
2914         fg.red = fg.green = fg.blue = 0;
2915         bg.red = bg.green = bg.blue = 0xffff;
2916         fg.alpha = bg.alpha = 0xffff;
2917
2918         wine_tsx11_lock();
2919         tmp_pixmap = XCreatePixmap( gdi_display, root_window, width, height,
2920                                     physdev_dst->pict_format->depth );
2921         pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2922         tmp_pict = pXRenderCreatePicture( gdi_display, tmp_pixmap, physdev_dst->pict_format,
2923                                           CPRepeat, &pa );
2924         wine_tsx11_unlock();
2925
2926         xrender_mono_blit( src_pict, tmp_pict, physdev_dst->format, &fg, &bg,
2927                            src->visrect.left, src->visrect.top, 0, 0, 1, 1, width, height );
2928     }
2929     else if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->pict_format)
2930     {
2931         /* we need a source picture with no alpha */
2932         enum wxr_format format = get_format_without_alpha( physdev_src->format );
2933         if (format != physdev_src->format)
2934         {
2935             wine_tsx11_lock();
2936             pa.subwindow_mode = IncludeInferiors;
2937             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2938             tmp_pict = pXRenderCreatePicture( gdi_display, physdev_src->x11dev->drawable,
2939                                               pict_formats[format], CPSubwindowMode|CPRepeat, &pa );
2940             wine_tsx11_unlock();
2941         }
2942     }
2943
2944     if (tmp_pict) src_pict = tmp_pict;
2945
2946     EnterCriticalSection( &xrender_cs );
2947     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2948
2949     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2950                   physdev_src->x11dev->dc_rect.left + src->x,
2951                   physdev_src->x11dev->dc_rect.top + src->y,
2952                   physdev_dst->x11dev->dc_rect.left + dst->x,
2953                   physdev_dst->x11dev->dc_rect.top + dst->y,
2954                   xscale, yscale, dst->width, dst->height );
2955
2956     wine_tsx11_lock();
2957     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2958     if (tmp_pixmap) XFreePixmap( gdi_display, tmp_pixmap );
2959     wine_tsx11_unlock();
2960
2961     LeaveCriticalSection( &xrender_cs );
2962     if (physdev_src != physdev_dst) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2963     X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2964     return TRUE;
2965 }
2966
2967 /***********************************************************************
2968  *           xrenderdrv_SelectBrush
2969  */
2970 static HBRUSH xrenderdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, HBITMAP bitmap,
2971                                       const BITMAPINFO *info, void *bits, UINT usage )
2972 {
2973     struct xrender_physdev *physdev = get_xrender_dev( dev );
2974     X_PHYSBITMAP *physbitmap;
2975     enum wxr_format format;
2976     BOOL delete_bitmap = FALSE;
2977     BITMAP bm;
2978     Pixmap pixmap;
2979     Picture src_pict, dst_pict;
2980     XRenderPictureAttributes pa;
2981
2982     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2983     if (!bitmap && !info) goto x11drv_fallback;
2984     if (physdev->format == WXR_FORMAT_MONO) goto x11drv_fallback;
2985
2986     if (!bitmap || !(physbitmap = X11DRV_get_phys_bitmap( bitmap )))
2987     {
2988         format = get_bitmap_format( info->bmiHeader.biBitCount );
2989         if (format == physdev->format || !pict_formats[format]) goto x11drv_fallback;
2990         if (!(bitmap = create_brush_bitmap( physdev->x11dev, info, bits, usage ))) return 0;
2991         physbitmap = X11DRV_get_phys_bitmap( bitmap );
2992         delete_bitmap = TRUE;
2993     }
2994     else
2995     {
2996         format = get_xrender_format_from_color_shifts( physbitmap->depth, &physbitmap->color_shifts );
2997         if (format == WXR_FORMAT_MONO || format == physdev->format || !pict_formats[format])
2998             goto x11drv_fallback;
2999     }
3000
3001     GetObjectW( bitmap, sizeof(bm), &bm );
3002
3003     X11DRV_DIB_Lock( physbitmap, DIB_Status_GdiMod );
3004
3005     wine_tsx11_lock();
3006     pixmap = XCreatePixmap( gdi_display, root_window, bm.bmWidth, bm.bmHeight,
3007                             physdev->pict_format->depth );
3008
3009     pa.repeat = RepeatNone;
3010     src_pict = pXRenderCreatePicture(gdi_display, physbitmap->pixmap, pict_formats[format], CPRepeat, &pa);
3011     dst_pict = pXRenderCreatePicture(gdi_display, pixmap, physdev->pict_format, CPRepeat, &pa);
3012
3013     xrender_blit( PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, bm.bmWidth, bm.bmHeight );
3014     pXRenderFreePicture( gdi_display, src_pict );
3015     pXRenderFreePicture( gdi_display, dst_pict );
3016
3017     if (physdev->x11dev->brush.pixmap) XFreePixmap( gdi_display, physdev->x11dev->brush.pixmap );
3018     physdev->x11dev->brush.pixmap = pixmap;
3019     physdev->x11dev->brush.fillStyle = FillTiled;
3020     physdev->x11dev->brush.pixel = 0;  /* ignored */
3021     wine_tsx11_unlock();
3022
3023     X11DRV_DIB_Unlock( physbitmap, TRUE );
3024     if (delete_bitmap) DeleteObject( bitmap );
3025     return hbrush;
3026
3027 x11drv_fallback:
3028     if (delete_bitmap) DeleteObject( bitmap );
3029     dev = GET_NEXT_PHYSDEV( dev, pSelectBrush );
3030     return dev->funcs->pSelectBrush( dev, hbrush, bitmap, info, bits, usage );
3031 }
3032
3033
3034 static const struct gdi_dc_funcs xrender_funcs =
3035 {
3036     NULL,                               /* pAbortDoc */
3037     NULL,                               /* pAbortPath */
3038     xrenderdrv_AlphaBlend,              /* pAlphaBlend */
3039     NULL,                               /* pAngleArc */
3040     NULL,                               /* pArc */
3041     NULL,                               /* pArcTo */
3042     NULL,                               /* pBeginPath */
3043     xrenderdrv_BlendImage,              /* pBlendImage */
3044     NULL,                               /* pChoosePixelFormat */
3045     NULL,                               /* pChord */
3046     NULL,                               /* pCloseFigure */
3047     xrenderdrv_CopyBitmap,              /* pCopyBitmap */
3048     xrenderdrv_CreateBitmap,            /* pCreateBitmap */
3049     xrenderdrv_CreateCompatibleDC,      /* pCreateCompatibleDC */
3050     xrenderdrv_CreateDC,                /* pCreateDC */
3051     NULL,                               /* pCreateDIBSection */
3052     xrenderdrv_DeleteBitmap,            /* pDeleteBitmap */
3053     xrenderdrv_DeleteDC,                /* pDeleteDC */
3054     NULL,                               /* pDeleteObject */
3055     NULL,                               /* pDescribePixelFormat */
3056     NULL,                               /* pDeviceCapabilities */
3057     NULL,                               /* pEllipse */
3058     NULL,                               /* pEndDoc */
3059     NULL,                               /* pEndPage */
3060     NULL,                               /* pEndPath */
3061     NULL,                               /* pEnumFonts */
3062     NULL,                               /* pEnumICMProfiles */
3063     NULL,                               /* pExcludeClipRect */
3064     NULL,                               /* pExtDeviceMode */
3065     xrenderdrv_ExtEscape,               /* pExtEscape */
3066     NULL,                               /* pExtFloodFill */
3067     NULL,                               /* pExtSelectClipRgn */
3068     xrenderdrv_ExtTextOut,              /* pExtTextOut */
3069     NULL,                               /* pFillPath */
3070     NULL,                               /* pFillRgn */
3071     NULL,                               /* pFlattenPath */
3072     NULL,                               /* pFontIsLinked */
3073     NULL,                               /* pFrameRgn */
3074     NULL,                               /* pGdiComment */
3075     NULL,                               /* pGdiRealizationInfo */
3076     NULL,                               /* pGetCharABCWidths */
3077     NULL,                               /* pGetCharABCWidthsI */
3078     NULL,                               /* pGetCharWidth */
3079     NULL,                               /* pGetDeviceCaps */
3080     NULL,                               /* pGetDeviceGammaRamp */
3081     NULL,                               /* pGetFontData */
3082     NULL,                               /* pGetFontUnicodeRanges */
3083     NULL,                               /* pGetGlyphIndices */
3084     NULL,                               /* pGetGlyphOutline */
3085     NULL,                               /* pGetICMProfile */
3086     xrenderdrv_GetImage,                /* pGetImage */
3087     NULL,                               /* pGetKerningPairs */
3088     NULL,                               /* pGetNearestColor */
3089     NULL,                               /* pGetOutlineTextMetrics */
3090     NULL,                               /* pGetPixel */
3091     NULL,                               /* pGetPixelFormat */
3092     NULL,                               /* pGetSystemPaletteEntries */
3093     NULL,                               /* pGetTextCharsetInfo */
3094     NULL,                               /* pGetTextExtentExPoint */
3095     NULL,                               /* pGetTextExtentExPointI */
3096     NULL,                               /* pGetTextFace */
3097     NULL,                               /* pGetTextMetrics */
3098     NULL,                               /* pGradientFill */
3099     NULL,                               /* pIntersectClipRect */
3100     NULL,                               /* pInvertRgn */
3101     NULL,                               /* pLineTo */
3102     NULL,                               /* pModifyWorldTransform */
3103     NULL,                               /* pMoveTo */
3104     NULL,                               /* pOffsetClipRgn */
3105     NULL,                               /* pOffsetViewportOrg */
3106     NULL,                               /* pOffsetWindowOrg */
3107     NULL,                               /* pPaintRgn */
3108     NULL,                               /* pPatBlt */
3109     NULL,                               /* pPie */
3110     NULL,                               /* pPolyBezier */
3111     NULL,                               /* pPolyBezierTo */
3112     NULL,                               /* pPolyDraw */
3113     NULL,                               /* pPolyPolygon */
3114     NULL,                               /* pPolyPolyline */
3115     NULL,                               /* pPolygon */
3116     NULL,                               /* pPolyline */
3117     NULL,                               /* pPolylineTo */
3118     xrenderdrv_PutImage,                /* pPutImage */
3119     NULL,                               /* pRealizeDefaultPalette */
3120     NULL,                               /* pRealizePalette */
3121     NULL,                               /* pRectangle */
3122     NULL,                               /* pResetDC */
3123     NULL,                               /* pRestoreDC */
3124     NULL,                               /* pRoundRect */
3125     NULL,                               /* pSaveDC */
3126     NULL,                               /* pScaleViewportExt */
3127     NULL,                               /* pScaleWindowExt */
3128     xrenderdrv_SelectBitmap,            /* pSelectBitmap */
3129     xrenderdrv_SelectBrush,             /* pSelectBrush */
3130     NULL,                               /* pSelectClipPath */
3131     xrenderdrv_SelectFont,              /* pSelectFont */
3132     NULL,                               /* pSelectPalette */
3133     NULL,                               /* pSelectPen */
3134     NULL,                               /* pSetArcDirection */
3135     NULL,                               /* pSetBkColor */
3136     NULL,                               /* pSetBkMode */
3137     NULL,                               /* pSetDCBrushColor */
3138     NULL,                               /* pSetDCPenColor */
3139     NULL,                               /* pSetDIBColorTable */
3140     NULL,                               /* pSetDIBitsToDevice */
3141     xrenderdrv_SetDeviceClipping,       /* pSetDeviceClipping */
3142     NULL,                               /* pSetDeviceGammaRamp */
3143     NULL,                               /* pSetLayout */
3144     NULL,                               /* pSetMapMode */
3145     NULL,                               /* pSetMapperFlags */
3146     NULL,                               /* pSetPixel */
3147     NULL,                               /* pSetPixelFormat */
3148     NULL,                               /* pSetPolyFillMode */
3149     NULL,                               /* pSetROP2 */
3150     NULL,                               /* pSetRelAbs */
3151     NULL,                               /* pSetStretchBltMode */
3152     NULL,                               /* pSetTextAlign */
3153     NULL,                               /* pSetTextCharacterExtra */
3154     NULL,                               /* pSetTextColor */
3155     NULL,                               /* pSetTextJustification */
3156     NULL,                               /* pSetViewportExt */
3157     NULL,                               /* pSetViewportOrg */
3158     NULL,                               /* pSetWindowExt */
3159     NULL,                               /* pSetWindowOrg */
3160     NULL,                               /* pSetWorldTransform */
3161     NULL,                               /* pStartDoc */
3162     NULL,                               /* pStartPage */
3163     xrenderdrv_StretchBlt,              /* pStretchBlt */
3164     NULL,                               /* pStretchDIBits */
3165     NULL,                               /* pStrokeAndFillPath */
3166     NULL,                               /* pStrokePath */
3167     NULL,                               /* pSwapBuffers */
3168     NULL,                               /* pUnrealizePalette */
3169     NULL,                               /* pWidenPath */
3170     /* OpenGL not supported */
3171 };
3172
3173 #else /* SONAME_LIBXRENDER */
3174
3175 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
3176 {
3177     TRACE("XRender support not compiled in.\n");
3178     return NULL;
3179 }
3180
3181 void X11DRV_XRender_Finalize(void)
3182 {
3183 }
3184
3185 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
3186 {
3187     return FALSE;
3188 }
3189
3190 #endif /* SONAME_LIBXRENDER */