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