winex11: Add window data locking to the system tray functions.
[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 WINE_DEFAULT_DEBUG_CHANNEL(xrender);
42
43 #ifdef SONAME_LIBXRENDER
44
45 WINE_DECLARE_DEBUG_CHANNEL(winediag);
46
47 #include <X11/Xlib.h>
48 #include <X11/extensions/Xrender.h>
49
50 #ifndef RepeatNone  /* added in 0.10 */
51 #define RepeatNone    0
52 #define RepeatNormal  1
53 #define RepeatPad     2
54 #define RepeatReflect 3
55 #endif
56
57 enum wxr_format
58 {
59   WXR_FORMAT_MONO,
60   WXR_FORMAT_GRAY,
61   WXR_FORMAT_X1R5G5B5,
62   WXR_FORMAT_X1B5G5R5,
63   WXR_FORMAT_R5G6B5,
64   WXR_FORMAT_B5G6R5,
65   WXR_FORMAT_R8G8B8,
66   WXR_FORMAT_B8G8R8,
67   WXR_FORMAT_A8R8G8B8,
68   WXR_FORMAT_B8G8R8A8,
69   WXR_FORMAT_X8R8G8B8,
70   WXR_FORMAT_B8G8R8X8,
71   WXR_NB_FORMATS,
72   WXR_INVALID_FORMAT = WXR_NB_FORMATS
73 };
74
75 typedef struct wine_xrender_format_template
76 {
77     unsigned int depth;
78     unsigned int alpha;
79     unsigned int alphaMask;
80     unsigned int red;
81     unsigned int redMask;
82     unsigned int green;
83     unsigned int greenMask;
84     unsigned int blue;
85     unsigned int blueMask;
86 } WineXRenderFormatTemplate;
87
88 static const WineXRenderFormatTemplate wxr_formats_template[WXR_NB_FORMATS] =
89 {
90     /* Format               depth   alpha   mask    red     mask    green   mask    blue    mask*/
91 /* WXR_FORMAT_MONO     */ { 1,      0,      0x01,   0,      0,      0,      0,      0,      0       },
92 /* WXR_FORMAT_GRAY     */ { 8,      0,      0xff,   0,      0,      0,      0,      0,      0       },
93 /* WXR_FORMAT_X1R5G5B5 */ { 16,     0,      0,      10,     0x1f,   5,      0x1f,   0,      0x1f    },
94 /* WXR_FORMAT_X1B5G5R5 */ { 16,     0,      0,      0,      0x1f,   5,      0x1f,   10,     0x1f    },
95 /* WXR_FORMAT_R5G6B5   */ { 16,     0,      0,      11,     0x1f,   5,      0x3f,   0,      0x1f    },
96 /* WXR_FORMAT_B5G6R5   */ { 16,     0,      0,      0,      0x1f,   5,      0x3f,   11,     0x1f    },
97 /* WXR_FORMAT_R8G8B8   */ { 24,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
98 /* WXR_FORMAT_B8G8R8   */ { 24,     0,      0,      0,      0xff,   8,      0xff,   16,     0xff    },
99 /* WXR_FORMAT_A8R8G8B8 */ { 32,     24,     0xff,   16,     0xff,   8,      0xff,   0,      0xff    },
100 /* WXR_FORMAT_B8G8R8A8 */ { 32,     0,      0xff,   8,      0xff,   16,     0xff,   24,     0xff    },
101 /* WXR_FORMAT_X8R8G8B8 */ { 32,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
102 /* WXR_FORMAT_B8G8R8X8 */ { 32,     0,      0,      8,      0xff,   16,     0xff,   24,     0xff    },
103 };
104
105 static const ColorShifts wxr_color_shifts[WXR_NB_FORMATS] =
106 {
107     /* format                phys red    phys green  phys blue   log red     log green   log blue */
108 /* WXR_FORMAT_MONO     */ { { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 }  },
109 /* WXR_FORMAT_GRAY     */ { { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 }  },
110 /* WXR_FORMAT_X1R5G5B5 */ { {10,5,31},  { 5,5,31},  { 0,5,31},  {10,5,31},  { 5,5,31},  { 0,5,31}  },
111 /* WXR_FORMAT_X1B5G5R5 */ { { 0,5,31},  { 5,5,31},  {10,5,31},  { 0,5,31},  { 5,5,31},  {10,5,31}  },
112 /* WXR_FORMAT_R5G6B5   */ { {11,5,31},  { 5,6,63},  { 0,5,31},  {11,5,31},  { 5,6,63},  { 0,5,31}  },
113 /* WXR_FORMAT_B5G6R5   */ { { 0,5,31},  { 5,6,63},  {11,5,31},  { 0,5,31},  { 5,6,63},  {11,5,31}  },
114 /* WXR_FORMAT_R8G8B8   */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
115 /* WXR_FORMAT_B8G8R8   */ { { 0,8,255}, { 8,8,255}, {16,8,255}, { 0,8,255}, { 8,8,255}, {16,8,255} },
116 /* WXR_FORMAT_A8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
117 /* WXR_FORMAT_B8G8R8A8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
118 /* WXR_FORMAT_X8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
119 /* WXR_FORMAT_B8G8R8X8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
120 };
121
122 static enum wxr_format default_format = WXR_INVALID_FORMAT;
123 static XRenderPictFormat *pict_formats[WXR_NB_FORMATS + 1 /* invalid format */];
124
125 typedef struct
126 {
127     LOGFONTW lf;
128     XFORM    xform;
129     SIZE     devsize;  /* size in device coords */
130     DWORD    hash;
131 } LFANDSIZE;
132
133 #define INITIAL_REALIZED_BUF_SIZE 128
134
135 typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
136
137 typedef struct
138 {
139     GlyphSet glyphset;
140     XRenderPictFormat *font_format;
141     int nrealized;
142     BOOL *realized;
143     XGlyphInfo *gis;
144 } gsCacheEntryFormat;
145
146 typedef struct
147 {
148     LFANDSIZE lfsz;
149     AA_Type aa_default;
150     gsCacheEntryFormat * format[AA_MAXVALUE];
151     INT count;
152     INT next;
153 } gsCacheEntry;
154
155 struct xrender_physdev
156 {
157     struct gdi_physdev dev;
158     X11DRV_PDEVICE    *x11dev;
159     HRGN               region;
160     enum wxr_format    format;
161     int                cache_index;
162     BOOL               update_clip;
163     Picture            pict;
164     Picture            pict_src;
165     XRenderPictFormat *pict_format;
166 };
167
168 static inline struct xrender_physdev *get_xrender_dev( PHYSDEV dev )
169 {
170     return (struct xrender_physdev *)dev;
171 }
172
173 static const struct gdi_dc_funcs xrender_funcs;
174
175 static gsCacheEntry *glyphsetCache = NULL;
176 static DWORD glyphsetCacheSize = 0;
177 static INT lastfree = -1;
178 static INT mru = -1;
179
180 #define INIT_CACHE_SIZE 10
181
182 static int antialias = 1;
183
184 static void *xrender_handle;
185
186 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
187 MAKE_FUNCPTR(XRenderAddGlyphs)
188 MAKE_FUNCPTR(XRenderChangePicture)
189 MAKE_FUNCPTR(XRenderComposite)
190 MAKE_FUNCPTR(XRenderCompositeText16)
191 MAKE_FUNCPTR(XRenderCreateGlyphSet)
192 MAKE_FUNCPTR(XRenderCreatePicture)
193 MAKE_FUNCPTR(XRenderFillRectangle)
194 MAKE_FUNCPTR(XRenderFindFormat)
195 MAKE_FUNCPTR(XRenderFindVisualFormat)
196 MAKE_FUNCPTR(XRenderFreeGlyphSet)
197 MAKE_FUNCPTR(XRenderFreePicture)
198 MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
199 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
200 MAKE_FUNCPTR(XRenderCreateLinearGradient)
201 #endif
202 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
203 MAKE_FUNCPTR(XRenderSetPictureTransform)
204 #endif
205 MAKE_FUNCPTR(XRenderQueryExtension)
206
207 #ifdef SONAME_LIBFONTCONFIG
208 #include <fontconfig/fontconfig.h>
209 MAKE_FUNCPTR(FcConfigSubstitute)
210 MAKE_FUNCPTR(FcDefaultSubstitute)
211 MAKE_FUNCPTR(FcFontMatch)
212 MAKE_FUNCPTR(FcInit)
213 MAKE_FUNCPTR(FcPatternCreate)
214 MAKE_FUNCPTR(FcPatternDestroy)
215 MAKE_FUNCPTR(FcPatternAddInteger)
216 MAKE_FUNCPTR(FcPatternAddString)
217 MAKE_FUNCPTR(FcPatternGetBool)
218 MAKE_FUNCPTR(FcPatternGetInteger)
219 MAKE_FUNCPTR(FcPatternGetString)
220 static void *fontconfig_handle;
221 static BOOL fontconfig_installed;
222 #endif
223
224 #undef MAKE_FUNCPTR
225
226 static CRITICAL_SECTION xrender_cs;
227 static CRITICAL_SECTION_DEBUG critsect_debug =
228 {
229     0, 0, &xrender_cs,
230     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
231       0, 0, { (DWORD_PTR)(__FILE__ ": xrender_cs") }
232 };
233 static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
234
235 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
236           ( ( (ULONG)_x4 << 24 ) |     \
237             ( (ULONG)_x3 << 16 ) |     \
238             ( (ULONG)_x2 <<  8 ) |     \
239               (ULONG)_x1         )
240
241 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
242
243 #define GASP_GRIDFIT 0x01
244 #define GASP_DOGRAY  0x02
245
246 #ifdef WORDS_BIGENDIAN
247 #define get_be_word(x) (x)
248 #define NATIVE_BYTE_ORDER MSBFirst
249 #else
250 #define get_be_word(x) RtlUshortByteSwap(x)
251 #define NATIVE_BYTE_ORDER LSBFirst
252 #endif
253
254 static BOOL has_alpha( enum wxr_format format )
255 {
256     return (format == WXR_FORMAT_A8R8G8B8 || format == WXR_FORMAT_B8G8R8A8);
257 }
258
259 static enum wxr_format get_format_without_alpha( enum wxr_format format )
260 {
261     switch (format)
262     {
263     case WXR_FORMAT_A8R8G8B8: return WXR_FORMAT_X8R8G8B8;
264     case WXR_FORMAT_B8G8R8A8: return WXR_FORMAT_B8G8R8X8;
265     default: return format;
266     }
267 }
268
269 static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
270 {
271     templ->id = 0;
272     templ->type = PictTypeDirect;
273     templ->depth = fmt->depth;
274     templ->direct.alpha = fmt->alpha;
275     templ->direct.alphaMask = fmt->alphaMask;
276     templ->direct.red = fmt->red;
277     templ->direct.redMask = fmt->redMask;
278     templ->direct.green = fmt->green;
279     templ->direct.greenMask = fmt->greenMask;
280     templ->direct.blue = fmt->blue;
281     templ->direct.blueMask = fmt->blueMask;
282     templ->colormap = 0;
283
284     *mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
285
286     return TRUE;
287 }
288
289 static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
290 {
291     if(fmt->depth != screen_depth)
292         return FALSE;
293     if( (fmt->redMask << fmt->red) != visual->red_mask)
294         return FALSE;
295     if( (fmt->greenMask << fmt->green) != visual->green_mask)
296         return FALSE;
297     if( (fmt->blueMask << fmt->blue) != visual->blue_mask)
298         return FALSE;
299
300     /* We never select a default ARGB visual */
301     if(fmt->alphaMask)
302         return FALSE;
303
304     return TRUE;
305 }
306
307 static int load_xrender_formats(void)
308 {
309     int count = 0;
310     unsigned int i;
311
312     for (i = 0; i < WXR_NB_FORMATS; i++)
313     {
314         XRenderPictFormat templ;
315
316         if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
317         {
318             pict_formats[i] = pXRenderFindVisualFormat(gdi_display, visual);
319             if (!pict_formats[i])
320             {
321                 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
322                 if (visual->class == DirectColor)
323                 {
324                     XVisualInfo info;
325                     if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
326                                           screen_depth, TrueColor, &info ))
327                     {
328                         pict_formats[i] = pXRenderFindVisualFormat(gdi_display, info.visual);
329                         if (pict_formats[i]) visual = info.visual;
330                     }
331                 }
332             }
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             pict_formats[i] = pXRenderFindFormat(gdi_display, mask, &templ, 0);
340         }
341         if (pict_formats[i])
342         {
343             count++;
344             TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats[i]->id, i);
345         }
346     }
347     return count;
348 }
349
350 /***********************************************************************
351  *   X11DRV_XRender_Init
352  *
353  * Let's see if our XServer has the extension available
354  *
355  */
356 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
357 {
358     int event_base, i;
359
360     if (!client_side_with_render) return NULL;
361     if (!(xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0))) return NULL;
362
363 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) return NULL
364 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0)
365     LOAD_FUNCPTR(XRenderAddGlyphs);
366     LOAD_FUNCPTR(XRenderChangePicture);
367     LOAD_FUNCPTR(XRenderComposite);
368     LOAD_FUNCPTR(XRenderCompositeText16);
369     LOAD_FUNCPTR(XRenderCreateGlyphSet);
370     LOAD_FUNCPTR(XRenderCreatePicture);
371     LOAD_FUNCPTR(XRenderFillRectangle);
372     LOAD_FUNCPTR(XRenderFindFormat);
373     LOAD_FUNCPTR(XRenderFindVisualFormat);
374     LOAD_FUNCPTR(XRenderFreeGlyphSet);
375     LOAD_FUNCPTR(XRenderFreePicture);
376     LOAD_FUNCPTR(XRenderSetPictureClipRectangles);
377     LOAD_FUNCPTR(XRenderQueryExtension);
378 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
379     LOAD_OPTIONAL_FUNCPTR(XRenderCreateLinearGradient);
380 #endif
381 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
382     LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform);
383 #endif
384 #undef LOAD_OPTIONAL_FUNCPTR
385 #undef LOAD_FUNCPTR
386
387     if (!pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base)) return NULL;
388
389     TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
390     if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
391     {
392         ERR_(winediag)("Wine has detected that you probably have a buggy version "
393                        "of libXrender.  Because of this client side font rendering "
394                        "will be disabled.  Please upgrade this library.\n");
395         return NULL;
396     }
397
398     if (!visual->red_mask || !visual->green_mask || !visual->blue_mask)
399     {
400         WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
401         return NULL;
402     }
403
404 #ifdef SONAME_LIBFONTCONFIG
405     if ((fontconfig_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0)))
406     {
407 #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;}
408         LOAD_FUNCPTR(FcConfigSubstitute);
409         LOAD_FUNCPTR(FcDefaultSubstitute);
410         LOAD_FUNCPTR(FcFontMatch);
411         LOAD_FUNCPTR(FcInit);
412         LOAD_FUNCPTR(FcPatternCreate);
413         LOAD_FUNCPTR(FcPatternDestroy);
414         LOAD_FUNCPTR(FcPatternAddInteger);
415         LOAD_FUNCPTR(FcPatternAddString);
416         LOAD_FUNCPTR(FcPatternGetBool);
417         LOAD_FUNCPTR(FcPatternGetInteger);
418         LOAD_FUNCPTR(FcPatternGetString);
419 #undef LOAD_FUNCPTR
420         fontconfig_installed = pFcInit();
421     }
422     else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG "\n" );
423
424 sym_not_found:
425 #endif
426
427     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
428                               sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
429
430     glyphsetCacheSize = INIT_CACHE_SIZE;
431     lastfree = 0;
432     for(i = 0; i < INIT_CACHE_SIZE; i++) {
433         glyphsetCache[i].next = i + 1;
434         glyphsetCache[i].count = -1;
435     }
436     glyphsetCache[i-1].next = -1;
437
438     if(screen_depth <= 8 || !client_side_antialias_with_render) antialias = 0;
439
440     return &xrender_funcs;
441 }
442
443 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
444 static void get_xrender_color( struct xrender_physdev *physdev, COLORREF src_color, XRenderColor *dst_color )
445 {
446     if (src_color & (1 << 24))  /* PALETTEINDEX */
447     {
448         HPALETTE pal = GetCurrentObject( physdev->dev.hdc, OBJ_PAL );
449         PALETTEENTRY pal_ent;
450
451         if (!GetPaletteEntries( pal, LOWORD(src_color), 1, &pal_ent ))
452             GetPaletteEntries( pal, 0, 1, &pal_ent );
453         dst_color->red   = pal_ent.peRed   * 257;
454         dst_color->green = pal_ent.peGreen * 257;
455         dst_color->blue  = pal_ent.peBlue  * 257;
456     }
457     else
458     {
459         if (src_color >> 16 == 0x10ff) src_color = 0; /* DIBINDEX */
460
461         dst_color->red   = GetRValue( src_color ) * 257;
462         dst_color->green = GetGValue( src_color ) * 257;
463         dst_color->blue  = GetBValue( src_color ) * 257;
464     }
465
466     if (physdev->format == WXR_FORMAT_MONO && !dst_color->red && !dst_color->green && !dst_color->blue)
467         dst_color->alpha = 0;
468     else
469         dst_color->alpha = 0xffff;
470 }
471
472 static enum wxr_format get_xrender_format_from_bitmapinfo( const BITMAPINFO *info )
473 {
474     if (info->bmiHeader.biPlanes != 1) return WXR_INVALID_FORMAT;
475
476     switch (info->bmiHeader.biBitCount)
477     {
478     case 1:
479         return WXR_FORMAT_MONO;
480     case 4:
481     case 8:
482         break;
483     case 24:
484         if (info->bmiHeader.biCompression != BI_RGB) break;
485         return WXR_FORMAT_R8G8B8;
486     case 16:
487     case 32:
488         if (info->bmiHeader.biCompression == BI_BITFIELDS)
489         {
490             DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
491             unsigned int i;
492
493             for (i = 0; i < WXR_NB_FORMATS; i++)
494             {
495                 if (info->bmiHeader.biBitCount == wxr_formats_template[i].depth &&
496                     colors[0] == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
497                     colors[1] == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
498                     colors[2] == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue))
499                     return i;
500             }
501             break;
502         }
503         if (info->bmiHeader.biCompression != BI_RGB) break;
504         return (info->bmiHeader.biBitCount == 16) ? WXR_FORMAT_X1R5G5B5 : WXR_FORMAT_A8R8G8B8;
505     }
506     return WXR_INVALID_FORMAT;
507 }
508
509 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
510 static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
511 {
512 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
513     XTransform xform = {{
514         { XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(xoffset) },
515         { XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(yoffset) },
516         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
517     }};
518
519     pXRenderSetPictureTransform(gdi_display, src_pict, &xform);
520 #endif
521 }
522
523 static void update_xrender_clipping( struct xrender_physdev *dev, HRGN rgn )
524 {
525     XRenderPictureAttributes pa;
526     RGNDATA *data;
527
528     if (!rgn)
529     {
530         pa.clip_mask = None;
531         pXRenderChangePicture( gdi_display, dev->pict, CPClipMask, &pa );
532     }
533     else if ((data = X11DRV_GetRegionData( rgn, 0 )))
534     {
535         pXRenderSetPictureClipRectangles( gdi_display, dev->pict,
536                                           dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top,
537                                           (XRectangle *)data->Buffer, data->rdh.nCount );
538         HeapFree( GetProcessHeap(), 0, data );
539     }
540 }
541
542
543 static Picture get_xrender_picture( struct xrender_physdev *dev, HRGN clip_rgn, const RECT *clip_rect )
544 {
545     if (!dev->pict && dev->pict_format)
546     {
547         XRenderPictureAttributes pa;
548
549         pa.subwindow_mode = IncludeInferiors;
550         dev->pict = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
551                                            dev->pict_format, CPSubwindowMode, &pa );
552         TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
553                dev->pict, dev->dev.hdc, dev->x11dev->drawable );
554         dev->update_clip = (dev->region != 0);
555     }
556
557     if (clip_rect)
558     {
559         HRGN rgn = CreateRectRgnIndirect( clip_rect );
560         if (clip_rgn) CombineRgn( rgn, rgn, clip_rgn, RGN_AND );
561         if (dev->region) CombineRgn( rgn, rgn, dev->region, RGN_AND );
562         update_xrender_clipping( dev, rgn );
563         DeleteObject( rgn );
564     }
565     else if (clip_rgn)
566     {
567         if (dev->region)
568         {
569             HRGN rgn = CreateRectRgn( 0, 0, 0, 0 );
570             CombineRgn( rgn, clip_rgn, dev->region, RGN_AND );
571             update_xrender_clipping( dev, rgn );
572             DeleteObject( rgn );
573         }
574         else update_xrender_clipping( dev, clip_rgn );
575     }
576     else if (dev->update_clip) update_xrender_clipping( dev, dev->region );
577
578     dev->update_clip = (clip_rect || clip_rgn);  /* have to update again if we are using a custom region */
579     return dev->pict;
580 }
581
582 static Picture get_xrender_picture_source( struct xrender_physdev *dev, BOOL repeat )
583 {
584     if (!dev->pict_src && dev->pict_format)
585     {
586         XRenderPictureAttributes pa;
587
588         pa.subwindow_mode = IncludeInferiors;
589         pa.repeat = repeat ? RepeatNormal : RepeatNone;
590         dev->pict_src = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
591                                                dev->pict_format, CPSubwindowMode|CPRepeat, &pa );
592
593         TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
594               dev->pict_src, dev->dev.hdc, dev->x11dev->drawable, pa.repeat);
595     }
596
597     return dev->pict_src;
598 }
599
600 static void free_xrender_picture( struct xrender_physdev *dev )
601 {
602     if (dev->pict || dev->pict_src)
603     {
604         XFlush( gdi_display );
605         if (dev->pict)
606         {
607             TRACE("freeing pict = %lx dc = %p\n", dev->pict, dev->dev.hdc);
608             pXRenderFreePicture(gdi_display, dev->pict);
609             dev->pict = 0;
610         }
611         if(dev->pict_src)
612         {
613             TRACE("freeing pict = %lx dc = %p\n", dev->pict_src, dev->dev.hdc);
614             pXRenderFreePicture(gdi_display, dev->pict_src);
615             dev->pict_src = 0;
616         }
617     }
618 }
619
620 /* return a mask picture used to force alpha to 0 */
621 static Picture get_no_alpha_mask(void)
622 {
623     static Pixmap pixmap;
624     static Picture pict;
625
626     EnterCriticalSection( &xrender_cs );
627     if (!pict)
628     {
629         XRenderPictureAttributes pa;
630         XRenderColor col;
631
632         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
633         pa.repeat = RepeatNormal;
634         pa.component_alpha = True;
635         pict = pXRenderCreatePicture( gdi_display, pixmap, pict_formats[WXR_FORMAT_A8R8G8B8],
636                                       CPRepeat|CPComponentAlpha, &pa );
637         col.red = col.green = col.blue = 0xffff;
638         col.alpha = 0;
639         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
640     }
641     LeaveCriticalSection( &xrender_cs );
642     return pict;
643 }
644
645 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
646 {
647   if(p1->hash != p2->hash) return TRUE;
648   if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE;
649   if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE;
650   if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
651   return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName);
652 }
653
654 #if 0
655 static void walk_cache(void)
656 {
657   int i;
658
659   EnterCriticalSection(&xrender_cs);
660   for(i=mru; i >= 0; i = glyphsetCache[i].next)
661     TRACE("item %d\n", i);
662   LeaveCriticalSection(&xrender_cs);
663 }
664 #endif
665
666 static int LookupEntry(LFANDSIZE *plfsz)
667 {
668   int i, prev_i = -1;
669
670   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
671     TRACE("%d\n", i);
672     if(glyphsetCache[i].count == -1) break; /* reached free list so stop */
673
674     if(!fontcmp(&glyphsetCache[i].lfsz, plfsz)) {
675       glyphsetCache[i].count++;
676       if(prev_i >= 0) {
677         glyphsetCache[prev_i].next = glyphsetCache[i].next;
678         glyphsetCache[i].next = mru;
679         mru = i;
680       }
681       TRACE("found font in cache %d\n", i);
682       return i;
683     }
684     prev_i = i;
685   }
686   TRACE("font not in cache\n");
687   return -1;
688 }
689
690 static void FreeEntry(int entry)
691 {
692     int format;
693
694     for(format = 0; format < AA_MAXVALUE; format++) {
695         gsCacheEntryFormat * formatEntry;
696
697         if( !glyphsetCache[entry].format[format] )
698             continue;
699
700         formatEntry = glyphsetCache[entry].format[format];
701
702         if(formatEntry->glyphset) {
703             pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
704             formatEntry->glyphset = 0;
705         }
706         if(formatEntry->nrealized) {
707             HeapFree(GetProcessHeap(), 0, formatEntry->realized);
708             formatEntry->realized = NULL;
709             HeapFree(GetProcessHeap(), 0, formatEntry->gis);
710             formatEntry->gis = NULL;
711             formatEntry->nrealized = 0;
712         }
713
714         HeapFree(GetProcessHeap(), 0, formatEntry);
715         glyphsetCache[entry].format[format] = NULL;
716     }
717 }
718
719 static int AllocEntry(void)
720 {
721   int best = -1, prev_best = -1, i, prev_i = -1;
722
723   if(lastfree >= 0) {
724     assert(glyphsetCache[lastfree].count == -1);
725     glyphsetCache[lastfree].count = 1;
726     best = lastfree;
727     lastfree = glyphsetCache[lastfree].next;
728     assert(best != mru);
729     glyphsetCache[best].next = mru;
730     mru = best;
731
732     TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
733     return mru;
734   }
735
736   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
737     if(glyphsetCache[i].count == 0) {
738       best = i;
739       prev_best = prev_i;
740     }
741     prev_i = i;
742   }
743
744   if(best >= 0) {
745     TRACE("freeing unused glyphset at cache %d\n", best);
746     FreeEntry(best);
747     glyphsetCache[best].count = 1;
748     if(prev_best >= 0) {
749       glyphsetCache[prev_best].next = glyphsetCache[best].next;
750       glyphsetCache[best].next = mru;
751       mru = best;
752     } else {
753       assert(mru == best);
754     }
755     return mru;
756   }
757
758   TRACE("Growing cache\n");
759   
760   if (glyphsetCache)
761     glyphsetCache = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
762                               glyphsetCache,
763                               (glyphsetCacheSize + INIT_CACHE_SIZE)
764                               * sizeof(*glyphsetCache));
765   else
766     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
767                               (glyphsetCacheSize + INIT_CACHE_SIZE)
768                               * sizeof(*glyphsetCache));
769
770   for(best = i = glyphsetCacheSize; i < glyphsetCacheSize + INIT_CACHE_SIZE;
771       i++) {
772     glyphsetCache[i].next = i + 1;
773     glyphsetCache[i].count = -1;
774   }
775   glyphsetCache[i-1].next = -1;
776   glyphsetCacheSize += INIT_CACHE_SIZE;
777
778   lastfree = glyphsetCache[best].next;
779   glyphsetCache[best].count = 1;
780   glyphsetCache[best].next = mru;
781   mru = best;
782   TRACE("new free cache slot at %d\n", mru);
783   return mru;
784 }
785
786 static BOOL get_gasp_flags(HDC hdc, WORD *flags)
787 {
788     DWORD size;
789     WORD *gasp, *buffer;
790     WORD num_recs;
791     DWORD ppem;
792     TEXTMETRICW tm;
793
794     *flags = 0;
795
796     size = GetFontData(hdc, MS_GASP_TAG,  0, NULL, 0);
797     if(size == GDI_ERROR)
798         return FALSE;
799
800     gasp = buffer = HeapAlloc(GetProcessHeap(), 0, size);
801     GetFontData(hdc, MS_GASP_TAG,  0, gasp, size);
802
803     GetTextMetricsW(hdc, &tm);
804     ppem = abs(X11DRV_YWStoDS(hdc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading));
805
806     gasp++;
807     num_recs = get_be_word(*gasp);
808     gasp++;
809     while(num_recs--)
810     {
811         *flags = get_be_word(*(gasp + 1));
812         if(ppem <= get_be_word(*gasp))
813             break;
814         gasp += 2;
815     }
816     TRACE("got flags %04x for ppem %d\n", *flags, ppem);
817
818     HeapFree(GetProcessHeap(), 0, buffer);
819     return TRUE;
820 }
821
822 static AA_Type get_antialias_type( HDC hdc, BOOL subpixel, BOOL hinter )
823 {
824     AA_Type ret;
825     WORD flags;
826     UINT font_smoothing_type, font_smoothing_orientation;
827
828     if (subpixel &&
829         SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE, 0, &font_smoothing_type, 0) &&
830         font_smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
831     {
832         if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION, 0,
833                                     &font_smoothing_orientation, 0) &&
834              font_smoothing_orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
835         {
836             ret = AA_BGR;
837         }
838         else
839             ret = AA_RGB;
840         /*FIXME
841           If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
842           But, Wine's subpixel rendering can support the portrait mode.
843          */
844     }
845     else if (!hinter || !get_gasp_flags(hdc, &flags) || flags & GASP_DOGRAY)
846         ret = AA_Grey;
847     else
848         ret = AA_None;
849
850     return ret;
851 }
852
853 static int GetCacheEntry( HDC hdc, LFANDSIZE *plfsz )
854 {
855     int ret;
856     int format;
857     gsCacheEntry *entry;
858     static int hinter = -1;
859     static int subpixel = -1;
860     BOOL font_smoothing;
861
862     if((ret = LookupEntry(plfsz)) != -1) return ret;
863
864     ret = AllocEntry();
865     entry = glyphsetCache + ret;
866     entry->lfsz = *plfsz;
867     for( format = 0; format < AA_MAXVALUE; format++ ) {
868         assert( !entry->format[format] );
869     }
870
871     if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY)
872     {
873         if(hinter == -1 || subpixel == -1)
874         {
875             RASTERIZER_STATUS status;
876             GetRasterizerCaps(&status, sizeof(status));
877             hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
878             subpixel = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
879         }
880
881         switch (plfsz->lf.lfQuality)
882         {
883             case ANTIALIASED_QUALITY:
884                 entry->aa_default = get_antialias_type( hdc, FALSE, hinter );
885                 return ret;  /* ignore further configuration */
886             case CLEARTYPE_QUALITY:
887             case CLEARTYPE_NATURAL_QUALITY:
888                 entry->aa_default = get_antialias_type( hdc, subpixel, hinter );
889                 break;
890             case DEFAULT_QUALITY:
891             case DRAFT_QUALITY:
892             case PROOF_QUALITY:
893             default:
894                 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0) &&
895                      font_smoothing)
896                 {
897                     entry->aa_default = get_antialias_type( hdc, subpixel, hinter );
898                 }
899                 else
900                     entry->aa_default = AA_None;
901                 break;
902         }
903
904         font_smoothing = TRUE;  /* default to enabled */
905 #ifdef SONAME_LIBFONTCONFIG
906         if (fontconfig_installed)
907         {
908             FcPattern *match, *pattern;
909             FcResult result;
910             char family[LF_FACESIZE * 4];
911
912 #if defined(__i386__) && defined(__GNUC__)
913             /* fontconfig generates floating point exceptions, mask them */
914             WORD cw, default_cw = 0x37f;
915             __asm__ __volatile__("fnstcw %0; fldcw %1" : "=m" (cw) : "m" (default_cw));
916 #endif
917
918             WideCharToMultiByte( CP_UTF8, 0, plfsz->lf.lfFaceName, -1, family, sizeof(family), NULL, NULL );
919             pattern = pFcPatternCreate();
920             pFcPatternAddString( pattern, FC_FAMILY, (FcChar8 *)family );
921             if (plfsz->lf.lfWeight != FW_DONTCARE)
922             {
923                 int weight;
924                 switch (plfsz->lf.lfWeight)
925                 {
926                 case FW_THIN:       weight = FC_WEIGHT_THIN; break;
927                 case FW_EXTRALIGHT: weight = FC_WEIGHT_EXTRALIGHT; break;
928                 case FW_LIGHT:      weight = FC_WEIGHT_LIGHT; break;
929                 case FW_NORMAL:     weight = FC_WEIGHT_NORMAL; break;
930                 case FW_MEDIUM:     weight = FC_WEIGHT_MEDIUM; break;
931                 case FW_SEMIBOLD:   weight = FC_WEIGHT_SEMIBOLD; break;
932                 case FW_BOLD:       weight = FC_WEIGHT_BOLD; break;
933                 case FW_EXTRABOLD:  weight = FC_WEIGHT_EXTRABOLD; break;
934                 case FW_HEAVY:      weight = FC_WEIGHT_HEAVY; break;
935                 default:            weight = (plfsz->lf.lfWeight - 80) / 4; break;
936                 }
937                 pFcPatternAddInteger( pattern, FC_WEIGHT, weight );
938             }
939             pFcPatternAddInteger( pattern, FC_SLANT, plfsz->lf.lfItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
940             pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
941             pFcDefaultSubstitute( pattern );
942             if ((match = pFcFontMatch( NULL, pattern, &result )))
943             {
944                 int rgba;
945                 FcBool antialias;
946
947                 if (pFcPatternGetBool( match, FC_ANTIALIAS, 0, &antialias ) != FcResultMatch)
948                     antialias = TRUE;
949                 if (pFcPatternGetInteger( match, FC_RGBA, 0, &rgba ) == FcResultMatch)
950                 {
951                     FcChar8 *file;
952                     if (pFcPatternGetString( match, FC_FILE, 0, &file ) != FcResultMatch) file = NULL;
953
954                     TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
955                            rgba, antialias, debugstr_w(plfsz->lf.lfFaceName), debugstr_a((char *)file) );
956
957                     switch (rgba)
958                     {
959                     case FC_RGBA_RGB:  entry->aa_default = AA_RGB; break;
960                     case FC_RGBA_BGR:  entry->aa_default = AA_BGR; break;
961                     case FC_RGBA_VRGB: entry->aa_default = AA_VRGB; break;
962                     case FC_RGBA_VBGR: entry->aa_default = AA_VBGR; break;
963                     case FC_RGBA_NONE: entry->aa_default = AA_Grey; break;
964                     }
965                 }
966                 if (!antialias) font_smoothing = FALSE;
967                 pFcPatternDestroy( match );
968             }
969             pFcPatternDestroy( pattern );
970
971 #if defined(__i386__) && defined(__GNUC__)
972             __asm__ __volatile__("fnclex; fldcw %0" : : "m" (cw));
973 #endif
974         }
975 #endif  /* SONAME_LIBFONTCONFIG */
976
977         /* now check Xft resources */
978         {
979             char *value;
980             BOOL antialias = TRUE;
981
982             if ((value = XGetDefault( gdi_display, "Xft", "antialias" )))
983             {
984                 if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
985                     value[0] == '0' || !strcasecmp( value, "off" ))
986                     antialias = FALSE;
987             }
988             if ((value = XGetDefault( gdi_display, "Xft", "rgba" )))
989             {
990                 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value, antialias );
991                 if (!strcmp( value, "rgb" )) entry->aa_default = AA_RGB;
992                 else if (!strcmp( value, "bgr" )) entry->aa_default = AA_BGR;
993                 else if (!strcmp( value, "vrgb" )) entry->aa_default = AA_VRGB;
994                 else if (!strcmp( value, "vbgr" )) entry->aa_default = AA_VBGR;
995                 else if (!strcmp( value, "none" )) entry->aa_default = AA_Grey;
996             }
997             if (!antialias) font_smoothing = FALSE;
998         }
999
1000         if (!font_smoothing) entry->aa_default = AA_None;
1001     }
1002     else
1003         entry->aa_default = AA_None;
1004
1005     return ret;
1006 }
1007
1008 static void dec_ref_cache(int index)
1009 {
1010     assert(index >= 0);
1011     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
1012     assert(glyphsetCache[index].count > 0);
1013     glyphsetCache[index].count--;
1014 }
1015
1016 static void lfsz_calc_hash(LFANDSIZE *plfsz)
1017 {
1018   DWORD hash = 0, *ptr, two_chars;
1019   WORD *pwc;
1020   int i;
1021
1022   hash ^= plfsz->devsize.cx;
1023   hash ^= plfsz->devsize.cy;
1024   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
1025     hash ^= *ptr;
1026   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
1027     hash ^= *ptr;
1028   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
1029     two_chars = *ptr;
1030     pwc = (WCHAR *)&two_chars;
1031     if(!*pwc) break;
1032     *pwc = toupperW(*pwc);
1033     pwc++;
1034     *pwc = toupperW(*pwc);
1035     hash ^= two_chars;
1036     if(!*pwc) break;
1037   }
1038   plfsz->hash = hash;
1039   return;
1040 }
1041
1042 /**********************************************************************
1043  *           xrenderdrv_SelectFont
1044  */
1045 static HFONT xrenderdrv_SelectFont( PHYSDEV dev, HFONT hfont )
1046 {
1047     LFANDSIZE lfsz;
1048     struct xrender_physdev *physdev = get_xrender_dev( dev );
1049     PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont );
1050     HFONT ret = next->funcs->pSelectFont( next, hfont );
1051
1052     if (!ret) return 0;
1053
1054     GetObjectW( hfont, sizeof(lfsz.lf), &lfsz.lf );
1055
1056     TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1057           lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
1058           lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
1059     lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
1060     lfsz.devsize.cx = X11DRV_XWStoDS( dev->hdc, lfsz.lf.lfWidth );
1061     lfsz.devsize.cy = X11DRV_YWStoDS( dev->hdc, lfsz.lf.lfHeight );
1062
1063     GetTransform( dev->hdc, 0x204, &lfsz.xform );
1064     TRACE("font transform %f %f %f %f\n", lfsz.xform.eM11, lfsz.xform.eM12,
1065           lfsz.xform.eM21, lfsz.xform.eM22);
1066
1067     if (GetGraphicsMode( dev->hdc ) == GM_COMPATIBLE && lfsz.xform.eM11 * lfsz.xform.eM22 < 0)
1068         lfsz.lf.lfOrientation = -lfsz.lf.lfOrientation;
1069
1070     /* Not used fields, would break hashing */
1071     lfsz.xform.eDx = lfsz.xform.eDy = 0;
1072
1073     lfsz_calc_hash(&lfsz);
1074
1075     EnterCriticalSection(&xrender_cs);
1076     if (physdev->cache_index != -1)
1077         dec_ref_cache( physdev->cache_index );
1078     physdev->cache_index = GetCacheEntry( dev->hdc, &lfsz );
1079     LeaveCriticalSection(&xrender_cs);
1080     return ret;
1081 }
1082
1083 static BOOL create_xrender_dc( PHYSDEV *pdev, enum wxr_format format )
1084 {
1085     X11DRV_PDEVICE *x11dev = get_x11drv_dev( *pdev );
1086     struct xrender_physdev *physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) );
1087
1088     if (!physdev) return FALSE;
1089     physdev->x11dev = x11dev;
1090     physdev->cache_index = -1;
1091     physdev->format = format;
1092     physdev->pict_format = pict_formats[format];
1093     push_dc_driver( pdev, &physdev->dev, &xrender_funcs );
1094     return TRUE;
1095 }
1096
1097 /* store the color mask data in the bitmap info structure */
1098 static void set_color_info( XRenderPictFormat *format, BITMAPINFO *info )
1099 {
1100     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1101
1102     info->bmiHeader.biPlanes      = 1;
1103     info->bmiHeader.biBitCount    = pixmap_formats[format->depth]->bits_per_pixel;
1104     info->bmiHeader.biCompression = BI_RGB;
1105     info->bmiHeader.biClrUsed     = 0;
1106
1107     switch (info->bmiHeader.biBitCount)
1108     {
1109     case 16:
1110         colors[0] = format->direct.redMask   << format->direct.red;
1111         colors[1] = format->direct.greenMask << format->direct.green;
1112         colors[2] = format->direct.blueMask  << format->direct.blue;
1113         info->bmiHeader.biCompression = BI_BITFIELDS;
1114         break;
1115     case 32:
1116         colors[0] = format->direct.redMask   << format->direct.red;
1117         colors[1] = format->direct.greenMask << format->direct.green;
1118         colors[2] = format->direct.blueMask  << format->direct.blue;
1119         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
1120             info->bmiHeader.biCompression = BI_BITFIELDS;
1121         break;
1122     }
1123 }
1124
1125
1126 /**********************************************************************
1127  *           xrenderdrv_CreateDC
1128  */
1129 static BOOL xrenderdrv_CreateDC( PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
1130                                  LPCWSTR output, const DEVMODEW* initData )
1131 {
1132     return create_xrender_dc( pdev, default_format );
1133 }
1134
1135 /**********************************************************************
1136  *           xrenderdrv_CreateCompatibleDC
1137  */
1138 static BOOL xrenderdrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
1139 {
1140     if (orig)  /* chain to x11drv first */
1141     {
1142         orig = GET_NEXT_PHYSDEV( orig, pCreateCompatibleDC );
1143         if (!orig->funcs->pCreateCompatibleDC( orig, pdev )) return FALSE;
1144     }
1145     /* otherwise we have been called by x11drv */
1146
1147     return create_xrender_dc( pdev, WXR_FORMAT_MONO );
1148 }
1149
1150 /**********************************************************************
1151  *           xrenderdrv_DeleteDC
1152  */
1153 static BOOL xrenderdrv_DeleteDC( PHYSDEV dev )
1154 {
1155     struct xrender_physdev *physdev = get_xrender_dev( dev );
1156
1157     free_xrender_picture( physdev );
1158
1159     EnterCriticalSection( &xrender_cs );
1160     if (physdev->cache_index != -1) dec_ref_cache( physdev->cache_index );
1161     LeaveCriticalSection( &xrender_cs );
1162
1163     HeapFree( GetProcessHeap(), 0, physdev );
1164     return TRUE;
1165 }
1166
1167 /**********************************************************************
1168  *           xrenderdrv_ExtEscape
1169  */
1170 static INT xrenderdrv_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data,
1171                                  INT out_count, LPVOID out_data )
1172 {
1173     struct xrender_physdev *physdev = get_xrender_dev( dev );
1174
1175     dev = GET_NEXT_PHYSDEV( dev, pExtEscape );
1176
1177     if (escape == X11DRV_ESCAPE && in_data && in_count >= sizeof(enum x11drv_escape_codes))
1178     {
1179         if (*(const enum x11drv_escape_codes *)in_data == X11DRV_SET_DRAWABLE)
1180         {
1181             BOOL ret = dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1182             if (ret) free_xrender_picture( physdev );  /* pict format doesn't change, only drawable */
1183             return ret;
1184         }
1185     }
1186     return dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1187 }
1188
1189 /***********************************************************************
1190  *           xrenderdrv_SetDeviceClipping
1191  */
1192 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev, HRGN rgn )
1193 {
1194     struct xrender_physdev *physdev = get_xrender_dev( dev );
1195
1196     physdev->region = rgn;
1197     physdev->update_clip = TRUE;
1198
1199     dev = GET_NEXT_PHYSDEV( dev, pSetDeviceClipping );
1200     dev->funcs->pSetDeviceClipping( dev, rgn );
1201 }
1202
1203
1204 /************************************************************************
1205  *   UploadGlyph
1206  *
1207  * Helper to ExtTextOut.  Must be called inside xrender_cs
1208  */
1209 static void UploadGlyph(struct xrender_physdev *physDev, int glyph, AA_Type format)
1210 {
1211     unsigned int buflen;
1212     char *buf;
1213     Glyph gid;
1214     GLYPHMETRICS gm;
1215     XGlyphInfo gi;
1216     gsCacheEntry *entry = glyphsetCache + physDev->cache_index;
1217     gsCacheEntryFormat *formatEntry;
1218     UINT ggo_format = GGO_GLYPH_INDEX;
1219     enum wxr_format wxr_format;
1220     static const char zero[4];
1221     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1222
1223     switch(format) {
1224     case AA_Grey:
1225         ggo_format |= WINE_GGO_GRAY16_BITMAP;
1226         break;
1227     case AA_RGB:
1228         ggo_format |= WINE_GGO_HRGB_BITMAP;
1229         break;
1230     case AA_BGR:
1231         ggo_format |= WINE_GGO_HBGR_BITMAP;
1232         break;
1233     case AA_VRGB:
1234         ggo_format |= WINE_GGO_VRGB_BITMAP;
1235         break;
1236     case AA_VBGR:
1237         ggo_format |= WINE_GGO_VBGR_BITMAP;
1238         break;
1239
1240     default:
1241         ERR("aa = %d - not implemented\n", format);
1242     case AA_None:
1243         ggo_format |= GGO_BITMAP;
1244         break;
1245     }
1246
1247     buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1248     if(buflen == GDI_ERROR) {
1249         if(format != AA_None) {
1250             format = AA_None;
1251             entry->aa_default = AA_None;
1252             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1253             buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1254         }
1255         if(buflen == GDI_ERROR) {
1256             WARN("GetGlyphOutlineW failed using default glyph\n");
1257             buflen = GetGlyphOutlineW(physDev->dev.hdc, 0, ggo_format, &gm, 0, NULL, &identity);
1258             if(buflen == GDI_ERROR) {
1259                 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1260                 buflen = GetGlyphOutlineW(physDev->dev.hdc, 0x20, ggo_format, &gm, 0, NULL, &identity);
1261                 if(buflen == GDI_ERROR) {
1262                     ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1263                     return;
1264                 }
1265             }
1266         }
1267         TRACE("Turning off antialiasing for this monochrome font\n");
1268     }
1269
1270     /* If there is nothing for the current type, we create the entry. */
1271     if( !entry->format[format] ) {
1272         entry->format[format] = HeapAlloc(GetProcessHeap(),
1273                                           HEAP_ZERO_MEMORY,
1274                                           sizeof(gsCacheEntryFormat));
1275     }
1276     formatEntry = entry->format[format];
1277
1278     if(formatEntry->nrealized <= glyph) {
1279         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1280
1281         if (formatEntry->realized)
1282             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1283                                       HEAP_ZERO_MEMORY,
1284                                       formatEntry->realized,
1285                                       formatEntry->nrealized * sizeof(BOOL));
1286         else
1287             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1288                                       HEAP_ZERO_MEMORY,
1289                                       formatEntry->nrealized * sizeof(BOOL));
1290
1291         if (formatEntry->gis)
1292             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1293                                    HEAP_ZERO_MEMORY,
1294                                    formatEntry->gis,
1295                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1296         else
1297             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1298                                    HEAP_ZERO_MEMORY,
1299                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1300     }
1301
1302
1303     if(formatEntry->glyphset == 0) {
1304         switch(format) {
1305             case AA_Grey:
1306                 wxr_format = WXR_FORMAT_GRAY;
1307                 break;
1308
1309             case AA_RGB:
1310             case AA_BGR:
1311             case AA_VRGB:
1312             case AA_VBGR:
1313                 wxr_format = WXR_FORMAT_A8R8G8B8;
1314                 break;
1315
1316             default:
1317                 ERR("aa = %d - not implemented\n", format);
1318             case AA_None:
1319                 wxr_format = WXR_FORMAT_MONO;
1320                 break;
1321         }
1322
1323         formatEntry->font_format = pict_formats[wxr_format];
1324         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format);
1325     }
1326
1327
1328     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1329     GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1330     formatEntry->realized[glyph] = TRUE;
1331
1332     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1333           buflen,
1334           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1335           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1336
1337     gi.width = gm.gmBlackBoxX;
1338     gi.height = gm.gmBlackBoxY;
1339     gi.x = -gm.gmptGlyphOrigin.x;
1340     gi.y = gm.gmptGlyphOrigin.y;
1341     gi.xOff = gm.gmCellIncX;
1342     gi.yOff = gm.gmCellIncY;
1343
1344     if(TRACE_ON(xrender)) {
1345         int pitch, i, j;
1346         char output[300];
1347         unsigned char *line;
1348
1349         if(format == AA_None) {
1350             pitch = ((gi.width + 31) / 32) * 4;
1351             for(i = 0; i < gi.height; i++) {
1352                 line = (unsigned char*) buf + i * pitch;
1353                 output[0] = '\0';
1354                 for(j = 0; j < pitch * 8; j++) {
1355                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1356                 }
1357                 TRACE("%s\n", output);
1358             }
1359         } else {
1360             static const char blks[] = " .:;!o*#";
1361             char str[2];
1362
1363             str[1] = '\0';
1364             pitch = ((gi.width + 3) / 4) * 4;
1365             for(i = 0; i < gi.height; i++) {
1366                 line = (unsigned char*) buf + i * pitch;
1367                 output[0] = '\0';
1368                 for(j = 0; j < pitch; j++) {
1369                     str[0] = blks[line[j] >> 5];
1370                     strcat(output, str);
1371                 }
1372                 TRACE("%s\n", output);
1373             }
1374         }
1375     }
1376
1377
1378     if(formatEntry->glyphset) {
1379         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1380             unsigned char *byte = (unsigned char*) buf, c;
1381             int i = buflen;
1382
1383             while(i--) {
1384                 c = *byte;
1385
1386                 /* magic to flip bit order */
1387                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1388                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1389                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1390
1391                 *byte++ = c;
1392             }
1393         }
1394         else if ( format != AA_Grey &&
1395                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1396         {
1397             unsigned int i, *data = (unsigned int *)buf;
1398             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1399         }
1400         gid = glyph;
1401
1402         /*
1403           XRenderCompositeText seems to ignore 0x0 glyphs when
1404           AA_None, which means we lose the advance width of glyphs
1405           like the space.  We'll pretend that such glyphs are 1x1
1406           bitmaps.
1407         */
1408
1409         if(buflen == 0)
1410             gi.width = gi.height = 1;
1411
1412         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1413                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1414         HeapFree(GetProcessHeap(), 0, buf);
1415     }
1416
1417     formatEntry->gis[glyph] = gi;
1418 }
1419
1420 /*************************************************************
1421  *                 get_tile_pict
1422  *
1423  * Returns an appropriate Picture for tiling the text colour.
1424  * Call and use result within the xrender_cs
1425  */
1426 static Picture get_tile_pict( enum wxr_format wxr_format, const XRenderColor *color)
1427 {
1428     static struct
1429     {
1430         Pixmap xpm;
1431         Picture pict;
1432         XRenderColor current_color;
1433     } tiles[WXR_NB_FORMATS], *tile;
1434
1435     tile = &tiles[wxr_format];
1436
1437     if(!tile->xpm)
1438     {
1439         XRenderPictureAttributes pa;
1440         XRenderPictFormat *pict_format = pict_formats[wxr_format];
1441
1442         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, pict_format->depth);
1443
1444         pa.repeat = RepeatNormal;
1445         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, pict_format, CPRepeat, &pa);
1446
1447         /* init current_color to something different from text_pixel */
1448         tile->current_color = *color;
1449         tile->current_color.red ^= 0xffff;
1450
1451         if (wxr_format == WXR_FORMAT_MONO)
1452         {
1453             /* for a 1bpp bitmap we always need a 1 in the tile */
1454             XRenderColor col;
1455             col.red = col.green = col.blue = 0;
1456             col.alpha = 0xffff;
1457             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1458         }
1459     }
1460
1461     if (memcmp( color, &tile->current_color, sizeof(*color) ) && wxr_format != WXR_FORMAT_MONO)
1462     {
1463         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, color, 0, 0, 1, 1);
1464         tile->current_color = *color;
1465     }
1466     return tile->pict;
1467 }
1468
1469 /*************************************************************
1470  *                 get_mask_pict
1471  *
1472  * Returns an appropriate Picture for masking with the specified alpha.
1473  * Call and use result within the xrender_cs
1474  */
1475 static Picture get_mask_pict( int alpha )
1476 {
1477     static Pixmap pixmap;
1478     static Picture pict;
1479     static int current_alpha;
1480
1481     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1482
1483     if (!pixmap)
1484     {
1485         XRenderPictureAttributes pa;
1486
1487         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1488         pa.repeat = RepeatNormal;
1489         pict = pXRenderCreatePicture( gdi_display, pixmap,
1490                                       pict_formats[WXR_FORMAT_A8R8G8B8], CPRepeat, &pa );
1491         current_alpha = -1;
1492     }
1493
1494     if (alpha != current_alpha)
1495     {
1496         XRenderColor col;
1497         col.red = col.green = col.blue = 0;
1498         col.alpha = current_alpha = alpha;
1499         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1500     }
1501     return pict;
1502 }
1503
1504 /***********************************************************************
1505  *           xrenderdrv_ExtTextOut
1506  */
1507 static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
1508                                    const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx )
1509 {
1510     struct xrender_physdev *physdev = get_xrender_dev( dev );
1511     gsCacheEntry *entry;
1512     gsCacheEntryFormat *formatEntry;
1513     AA_Type aa_type = AA_None;
1514     unsigned int idx;
1515     Picture pict, tile_pict = 0;
1516     XGlyphElt16 *elts;
1517     POINT offset, desired, current;
1518     int render_op = PictOpOver;
1519     XRenderColor col;
1520     RECT rect, bounds;
1521
1522     get_xrender_color( physdev, GetTextColor( physdev->dev.hdc ), &col );
1523     pict = get_xrender_picture( physdev, 0, (flags & ETO_CLIPPED) ? lprect : NULL );
1524
1525     if(flags & ETO_OPAQUE)
1526     {
1527         XRenderColor bg;
1528
1529         if (physdev->format == WXR_FORMAT_MONO)
1530             /* use the inverse of the text color */
1531             bg.red = bg.green = bg.blue = bg.alpha = ~col.alpha;
1532         else
1533             get_xrender_color( physdev, GetBkColor( physdev->dev.hdc ), &bg );
1534
1535         set_xrender_transformation( pict, 1, 1, 0, 0 );
1536         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &bg,
1537                                physdev->x11dev->dc_rect.left + lprect->left,
1538                                physdev->x11dev->dc_rect.top + lprect->top,
1539                                lprect->right - lprect->left,
1540                                lprect->bottom - lprect->top );
1541         add_device_bounds( physdev->x11dev, lprect );
1542     }
1543
1544     if(count == 0) return TRUE;
1545
1546     EnterCriticalSection(&xrender_cs);
1547
1548     entry = glyphsetCache + physdev->cache_index;
1549     aa_type = entry->aa_default;
1550     formatEntry = entry->format[aa_type];
1551
1552     for(idx = 0; idx < count; idx++) {
1553         if( !formatEntry ) {
1554             UploadGlyph(physdev, wstr[idx], aa_type);
1555             /* re-evaluate antialias since aa_default may have changed */
1556             aa_type = entry->aa_default;
1557             formatEntry = entry->format[aa_type];
1558         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1559             UploadGlyph(physdev, wstr[idx], aa_type);
1560         }
1561     }
1562     if (!formatEntry)
1563     {
1564         WARN("could not upload requested glyphs\n");
1565         LeaveCriticalSection(&xrender_cs);
1566         return FALSE;
1567     }
1568
1569     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1570           physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
1571
1572     elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1573
1574     /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1575        So we pass zeros to the function and move to our starting position using the first
1576        element of the elts array. */
1577
1578     desired.x = physdev->x11dev->dc_rect.left + x;
1579     desired.y = physdev->x11dev->dc_rect.top + y;
1580     offset.x = offset.y = 0;
1581     current.x = current.y = 0;
1582
1583     tile_pict = get_tile_pict(physdev->format, &col);
1584
1585     /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1586      */
1587     if (physdev->format == WXR_FORMAT_MONO && col.red == 0 && col.green == 0 && col.blue == 0)
1588         render_op = PictOpOutReverse; /* This gives us 'black' text */
1589
1590     reset_bounds( &bounds );
1591     for(idx = 0; idx < count; idx++)
1592     {
1593         elts[idx].glyphset = formatEntry->glyphset;
1594         elts[idx].chars = wstr + idx;
1595         elts[idx].nchars = 1;
1596         elts[idx].xOff = desired.x - current.x;
1597         elts[idx].yOff = desired.y - current.y;
1598
1599         current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1600         current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1601
1602         rect.left   = desired.x - physdev->x11dev->dc_rect.left - formatEntry->gis[wstr[idx]].x;
1603         rect.top    = desired.y - physdev->x11dev->dc_rect.top - formatEntry->gis[wstr[idx]].y;
1604         rect.right  = rect.left + formatEntry->gis[wstr[idx]].width;
1605         rect.bottom = rect.top  + formatEntry->gis[wstr[idx]].height;
1606         add_bounds_rect( &bounds, &rect );
1607
1608         if(!lpDx)
1609         {
1610             desired.x += formatEntry->gis[wstr[idx]].xOff;
1611             desired.y += formatEntry->gis[wstr[idx]].yOff;
1612         }
1613         else
1614         {
1615             if(flags & ETO_PDY)
1616             {
1617                 offset.x += lpDx[idx * 2];
1618                 offset.y += lpDx[idx * 2 + 1];
1619             }
1620             else
1621                 offset.x += lpDx[idx];
1622             desired.x = physdev->x11dev->dc_rect.left + x + offset.x;
1623             desired.y = physdev->x11dev->dc_rect.top  + y + offset.y;
1624         }
1625     }
1626
1627     /* Make sure we don't have any transforms set from a previous call */
1628     set_xrender_transformation(pict, 1, 1, 0, 0);
1629     pXRenderCompositeText16(gdi_display, render_op,
1630                             tile_pict,
1631                             pict,
1632                             formatEntry->font_format,
1633                             0, 0, 0, 0, elts, count);
1634     HeapFree(GetProcessHeap(), 0, elts);
1635
1636     LeaveCriticalSection(&xrender_cs);
1637     add_device_bounds( physdev->x11dev, &bounds );
1638     return TRUE;
1639 }
1640
1641 /* multiply the alpha channel of a picture */
1642 static void multiply_alpha( Picture pict, XRenderPictFormat *format, int alpha,
1643                             int x, int y, int width, int height )
1644 {
1645     XRenderPictureAttributes pa;
1646     Pixmap src_pixmap, mask_pixmap;
1647     Picture src_pict, mask_pict;
1648     XRenderColor color;
1649
1650     src_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
1651     mask_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
1652     pa.repeat = RepeatNormal;
1653     src_pict = pXRenderCreatePicture( gdi_display, src_pixmap, format, CPRepeat, &pa );
1654     pa.component_alpha = True;
1655     mask_pict = pXRenderCreatePicture( gdi_display, mask_pixmap, format, CPRepeat|CPComponentAlpha, &pa );
1656     color.red = color.green = color.blue = color.alpha = 0xffff;
1657     pXRenderFillRectangle( gdi_display, PictOpSrc, src_pict, &color, 0, 0, 1, 1 );
1658     color.alpha = alpha;
1659     pXRenderFillRectangle( gdi_display, PictOpSrc, mask_pict, &color, 0, 0, 1, 1 );
1660     pXRenderComposite( gdi_display, PictOpInReverse, src_pict, mask_pict, pict,
1661                        0, 0, 0, 0, x, y, width, height );
1662     pXRenderFreePicture( gdi_display, src_pict );
1663     pXRenderFreePicture( gdi_display, mask_pict );
1664     XFreePixmap( gdi_display, src_pixmap );
1665     XFreePixmap( gdi_display, mask_pixmap );
1666 }
1667
1668 /* Helper function for (stretched) blitting using xrender */
1669 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
1670                           int x_src, int y_src, int width_src, int height_src,
1671                           int x_dst, int y_dst, int width_dst, int height_dst,
1672                           double xscale, double yscale )
1673 {
1674     int x_offset, y_offset;
1675
1676     if (width_src < 0)
1677     {
1678         x_src += width_src + 1;
1679         width_src = -width_src;
1680     }
1681     if (height_src < 0)
1682     {
1683         y_src += height_src + 1;
1684         height_src = -height_src;
1685     }
1686     if (width_dst < 0)
1687     {
1688         x_dst += width_dst + 1;
1689         width_dst = -width_dst;
1690     }
1691     if (height_dst < 0)
1692     {
1693         y_dst += height_dst + 1;
1694         height_dst = -height_dst;
1695     }
1696
1697     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
1698      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
1699      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
1700     if(xscale != 1.0 || yscale != 1.0)
1701     {
1702         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1703          * in the wrong quadrant of the x-y plane.
1704          */
1705         x_offset = (xscale < 0) ? -width_dst : 0;
1706         y_offset = (yscale < 0) ? -height_dst : 0;
1707         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1708     }
1709     else
1710     {
1711         x_offset = x_src;
1712         y_offset = y_src;
1713         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1714     }
1715     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
1716                        x_offset, y_offset, 0, 0, x_dst, y_dst, width_dst, height_dst );
1717 }
1718
1719 /* Helper function for (stretched) mono->color blitting using xrender */
1720 static void xrender_mono_blit( Picture src_pict, Picture dst_pict,
1721                                enum wxr_format dst_format, XRenderColor *fg, XRenderColor *bg,
1722                                int x_src, int y_src, int width_src, int height_src,
1723                                int x_dst, int y_dst, int width_dst, int height_dst,
1724                                double xscale, double yscale )
1725 {
1726     Picture tile_pict;
1727     int x_offset, y_offset;
1728     XRenderColor color;
1729
1730     if (width_src < 0)
1731     {
1732         x_src += width_src + 1;
1733         width_src = -width_src;
1734     }
1735     if (height_src < 0)
1736     {
1737         y_src += height_src + 1;
1738         height_src = -height_src;
1739     }
1740     if (width_dst < 0)
1741     {
1742         x_dst += width_dst + 1;
1743         width_dst = -width_dst;
1744     }
1745     if (height_dst < 0)
1746     {
1747         y_dst += height_dst + 1;
1748         height_dst = -height_dst;
1749     }
1750
1751     /* When doing a mono->color blit, the source data is used as mask, and the source picture
1752      * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
1753      * the tile data.
1754      */
1755     EnterCriticalSection( &xrender_cs );
1756     color = *bg;
1757     color.alpha = 0xffff;  /* tile pict needs 100% alpha */
1758     tile_pict = get_tile_pict( dst_format, &color );
1759
1760     pXRenderFillRectangle( gdi_display, PictOpSrc, dst_pict, fg, x_dst, y_dst, width_dst, height_dst );
1761
1762     if (xscale != 1.0 || yscale != 1.0)
1763     {
1764         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1765          * in the wrong quadrant of the x-y plane.
1766          */
1767         x_offset = (xscale < 0) ? -width_dst : 0;
1768         y_offset = (yscale < 0) ? -height_dst : 0;
1769         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1770     }
1771     else
1772     {
1773         x_offset = x_src;
1774         y_offset = y_src;
1775         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1776     }
1777     pXRenderComposite(gdi_display, PictOpOver, tile_pict, src_pict, dst_pict,
1778                       0, 0, x_offset, y_offset, x_dst, y_dst, width_dst, height_dst );
1779     LeaveCriticalSection( &xrender_cs );
1780
1781     /* force the alpha channel for background pixels, it has been set to 100% by the tile */
1782     if (bg->alpha != 0xffff && (dst_format == WXR_FORMAT_A8R8G8B8 || dst_format == WXR_FORMAT_B8G8R8A8))
1783         multiply_alpha( dst_pict, pict_formats[dst_format], bg->alpha,
1784                         x_dst, y_dst, width_dst, height_dst );
1785 }
1786
1787 /* create a pixmap and render picture for an image */
1788 static DWORD create_image_pixmap( BITMAPINFO *info, const struct gdi_image_bits *bits,
1789                                   struct bitblt_coords *src, enum wxr_format format,
1790                                   Pixmap *pixmap, Picture *pict, BOOL *use_repeat )
1791 {
1792     DWORD ret;
1793     int width = src->visrect.right - src->visrect.left;
1794     int height = src->visrect.bottom - src->visrect.top;
1795     int depth = pict_formats[format]->depth;
1796     struct gdi_image_bits dst_bits;
1797     XRenderPictureAttributes pa;
1798     GC gc;
1799     XImage *image;
1800
1801     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1802                           info->bmiHeader.biWidth, height, 32, 0 );
1803     if (!image) return ERROR_OUTOFMEMORY;
1804
1805     ret = copy_image_bits( info, (format == WXR_FORMAT_R8G8B8), image, bits, &dst_bits, src, NULL, ~0u );
1806     if (ret) return ret;
1807
1808     image->data = dst_bits.ptr;
1809
1810     *use_repeat = (width == 1 && height == 1);
1811     pa.repeat = *use_repeat ? RepeatNormal : RepeatNone;
1812
1813     *pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1814     gc = XCreateGC( gdi_display, *pixmap, 0, NULL );
1815     XPutImage( gdi_display, *pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1816     *pict = pXRenderCreatePicture( gdi_display, *pixmap, pict_formats[format], CPRepeat, &pa );
1817     XFreeGC( gdi_display, gc );
1818
1819     /* make coordinates relative to the pixmap */
1820     src->x -= src->visrect.left;
1821     src->y -= src->visrect.top;
1822     OffsetRect( &src->visrect, -src->visrect.left, -src->visrect.top );
1823
1824     image->data = NULL;
1825     XDestroyImage( image );
1826     if (dst_bits.free) dst_bits.free( &dst_bits );
1827     return ret;
1828 }
1829
1830 static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
1831                                   Drawable drawable, const struct bitblt_coords *src,
1832                                   const struct bitblt_coords *dst )
1833 {
1834     int x_dst, y_dst;
1835     Picture src_pict = 0, dst_pict, mask_pict = 0;
1836     double xscale = src->width / (double)dst->width;
1837     double yscale = src->height / (double)dst->height;
1838
1839     if (drawable)  /* using an intermediate pixmap */
1840     {
1841         x_dst = dst->x;
1842         y_dst = dst->y;
1843         dst_pict = pXRenderCreatePicture( gdi_display, drawable, physdev_dst->pict_format, 0, NULL );
1844     }
1845     else
1846     {
1847         x_dst = physdev_dst->x11dev->dc_rect.left + dst->x;
1848         y_dst = physdev_dst->x11dev->dc_rect.top + dst->y;
1849         dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
1850     }
1851
1852     src_pict = get_xrender_picture_source( physdev_src, FALSE );
1853
1854     /* mono -> color */
1855     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
1856     {
1857         XRenderColor fg, bg;
1858
1859         get_xrender_color( physdev_dst, GetTextColor( physdev_dst->dev.hdc ), &fg );
1860         get_xrender_color( physdev_dst, GetBkColor( physdev_dst->dev.hdc ), &bg );
1861         fg.alpha = bg.alpha = 0;
1862
1863         xrender_mono_blit( src_pict, dst_pict, physdev_dst->format, &fg, &bg,
1864                            physdev_src->x11dev->dc_rect.left + src->x,
1865                            physdev_src->x11dev->dc_rect.top + src->y,
1866                            src->width, src->height, x_dst, y_dst, dst->width, dst->height, xscale, yscale );
1867     }
1868     else /* color -> color (can be at different depths) or mono -> mono */
1869     {
1870         if (physdev_dst->pict_format->depth == 32 && physdev_src->pict_format->depth < 32)
1871             mask_pict = get_no_alpha_mask();
1872
1873         xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict,
1874                       physdev_src->x11dev->dc_rect.left + src->x,
1875                       physdev_src->x11dev->dc_rect.top + src->y,
1876                       src->width, src->height, x_dst, y_dst, dst->width, dst->height, xscale, yscale );
1877     }
1878
1879     if (drawable) pXRenderFreePicture( gdi_display, dst_pict );
1880 }
1881
1882
1883 static void xrender_put_image( Pixmap src_pixmap, Picture src_pict, Picture mask_pict, HRGN clip,
1884                                XRenderPictFormat *dst_format, struct xrender_physdev *physdev,
1885                                Drawable drawable, struct bitblt_coords *src,
1886                                struct bitblt_coords *dst, BOOL use_repeat )
1887 {
1888     int x_dst, y_dst;
1889     Picture dst_pict;
1890     double xscale, yscale;
1891
1892     if (drawable)  /* using an intermediate pixmap */
1893     {
1894         RGNDATA *clip_data = NULL;
1895
1896         if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1897         x_dst = dst->x;
1898         y_dst = dst->y;
1899         dst_pict = pXRenderCreatePicture( gdi_display, drawable, dst_format, 0, NULL );
1900         if (clip_data)
1901             pXRenderSetPictureClipRectangles( gdi_display, dst_pict, 0, 0,
1902                                               (XRectangle *)clip_data->Buffer, clip_data->rdh.nCount );
1903         HeapFree( GetProcessHeap(), 0, clip_data );
1904     }
1905     else
1906     {
1907         x_dst = physdev->x11dev->dc_rect.left + dst->x;
1908         y_dst = physdev->x11dev->dc_rect.top + dst->y;
1909         dst_pict = get_xrender_picture( physdev, clip, &dst->visrect );
1910     }
1911
1912     if (!use_repeat)
1913     {
1914         xscale = src->width / (double)dst->width;
1915         yscale = src->height / (double)dst->height;
1916     }
1917     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
1918
1919     xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict, src->x, src->y, src->width, src->height,
1920                   x_dst, y_dst, dst->width, dst->height, xscale, yscale );
1921
1922     if (drawable) pXRenderFreePicture( gdi_display, dst_pict );
1923 }
1924
1925
1926 /***********************************************************************
1927  *           xrenderdrv_StretchBlt
1928  */
1929 static BOOL xrenderdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
1930                                    PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
1931 {
1932     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
1933     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
1934     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
1935
1936     if (src_dev->funcs != dst_dev->funcs)
1937     {
1938         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
1939         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
1940     }
1941
1942     /* XRender is of no use for color -> mono */
1943     if (physdev_dst->format == WXR_FORMAT_MONO && physdev_src->format != WXR_FORMAT_MONO)
1944         goto x11drv_fallback;
1945
1946     /* if not stretching, we only need to handle format conversion */
1947     if (!stretch && physdev_dst->format == physdev_src->format) goto x11drv_fallback;
1948
1949     if (rop != SRCCOPY)
1950     {
1951         GC tmpGC;
1952         Pixmap tmp_pixmap;
1953         struct bitblt_coords tmp;
1954
1955         /* make coordinates relative to tmp pixmap */
1956         tmp = *dst;
1957         tmp.x -= tmp.visrect.left;
1958         tmp.y -= tmp.visrect.top;
1959         OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
1960
1961         tmpGC = XCreateGC( gdi_display, physdev_dst->x11dev->drawable, 0, NULL );
1962         XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
1963         XSetGraphicsExposures( gdi_display, tmpGC, False );
1964         tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
1965                                     tmp.visrect.bottom - tmp.visrect.top, physdev_dst->pict_format->depth );
1966
1967         xrender_stretch_blit( physdev_src, physdev_dst, tmp_pixmap, src, &tmp );
1968         execute_rop( physdev_dst->x11dev, tmp_pixmap, tmpGC, &dst->visrect, rop );
1969
1970         XFreePixmap( gdi_display, tmp_pixmap );
1971         XFreeGC( gdi_display, tmpGC );
1972     }
1973     else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
1974
1975     add_device_bounds( physdev_dst->x11dev, &dst->visrect );
1976     return TRUE;
1977
1978 x11drv_fallback:
1979     return X11DRV_StretchBlt( &physdev_dst->x11dev->dev, dst, &physdev_src->x11dev->dev, src, rop );
1980 }
1981
1982
1983 /***********************************************************************
1984  *           xrenderdrv_PutImage
1985  */
1986 static DWORD xrenderdrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1987                                   const struct gdi_image_bits *bits, struct bitblt_coords *src,
1988                                   struct bitblt_coords *dst, DWORD rop )
1989 {
1990     struct xrender_physdev *physdev = get_xrender_dev( dev );
1991     DWORD ret;
1992     Pixmap tmp_pixmap;
1993     GC gc;
1994     enum wxr_format src_format, dst_format;
1995     XRenderPictFormat *pict_format;
1996     Pixmap src_pixmap;
1997     Picture src_pict, mask_pict = 0;
1998     BOOL use_repeat;
1999
2000     dst_format = physdev->format;
2001     src_format = get_xrender_format_from_bitmapinfo( info );
2002     if (!(pict_format = pict_formats[src_format])) goto update_format;
2003
2004     /* make sure we can create an image with the same bpp */
2005     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2006         goto update_format;
2007
2008     /* mono <-> color conversions not supported */
2009     if ((src_format != dst_format) && (src_format == WXR_FORMAT_MONO || dst_format == WXR_FORMAT_MONO))
2010         goto x11drv_fallback;
2011
2012     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2013
2014     if (!has_alpha( src_format ) && has_alpha( dst_format )) mask_pict = get_no_alpha_mask();
2015
2016     ret = create_image_pixmap( info, bits, src, src_format, &src_pixmap, &src_pict, &use_repeat );
2017     if (!ret)
2018     {
2019         struct bitblt_coords tmp;
2020
2021         if (rop != SRCCOPY)
2022         {
2023             BOOL restore_region = add_extra_clipping_region( physdev->x11dev, clip );
2024
2025             /* make coordinates relative to tmp pixmap */
2026             tmp = *dst;
2027             tmp.x -= tmp.visrect.left;
2028             tmp.y -= tmp.visrect.top;
2029             OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2030
2031             gc = XCreateGC( gdi_display, physdev->x11dev->drawable, 0, NULL );
2032             XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
2033             XSetGraphicsExposures( gdi_display, gc, False );
2034             tmp_pixmap = XCreatePixmap( gdi_display, root_window,
2035                                         tmp.visrect.right - tmp.visrect.left,
2036                                         tmp.visrect.bottom - tmp.visrect.top,
2037                                         physdev->pict_format->depth );
2038
2039             xrender_put_image( src_pixmap, src_pict, mask_pict, NULL, physdev->pict_format,
2040                                NULL, tmp_pixmap, src, &tmp, use_repeat );
2041             execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
2042
2043             XFreePixmap( gdi_display, tmp_pixmap );
2044             XFreeGC( gdi_display, gc );
2045             if (restore_region) restore_clipping_region( physdev->x11dev );
2046         }
2047         else xrender_put_image( src_pixmap, src_pict, mask_pict, clip,
2048                                 physdev->pict_format, physdev, 0, src, dst, use_repeat );
2049
2050         add_device_bounds( physdev->x11dev, &dst->visrect );
2051
2052         pXRenderFreePicture( gdi_display, src_pict );
2053         XFreePixmap( gdi_display, src_pixmap );
2054     }
2055     return ret;
2056
2057 update_format:
2058     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2059     set_color_info( pict_formats[dst_format], info );
2060     return ERROR_BAD_FORMAT;
2061
2062 x11drv_fallback:
2063     dev = GET_NEXT_PHYSDEV( dev, pPutImage );
2064     return dev->funcs->pPutImage( dev, clip, info, bits, src, dst, rop );
2065 }
2066
2067
2068 /***********************************************************************
2069  *           xrenderdrv_BlendImage
2070  */
2071 static DWORD xrenderdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits,
2072                                     struct bitblt_coords *src, struct bitblt_coords *dst,
2073                                     BLENDFUNCTION func )
2074 {
2075     struct xrender_physdev *physdev = get_xrender_dev( dev );
2076     DWORD ret;
2077     enum wxr_format format;
2078     XRenderPictFormat *pict_format;
2079     Picture dst_pict, src_pict, mask_pict;
2080     Pixmap src_pixmap;
2081     BOOL use_repeat;
2082
2083     format = get_xrender_format_from_bitmapinfo( info );
2084     if (!(func.AlphaFormat & AC_SRC_ALPHA))
2085         format = get_format_without_alpha( format );
2086     else if (format != WXR_FORMAT_A8R8G8B8)
2087         return ERROR_INVALID_PARAMETER;
2088
2089     if (!(pict_format = pict_formats[format])) goto update_format;
2090
2091     /* make sure we can create an image with the same bpp */
2092     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2093         goto update_format;
2094
2095     if (format == WXR_FORMAT_MONO && physdev->format != WXR_FORMAT_MONO)
2096         goto update_format;
2097
2098     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2099
2100     ret = create_image_pixmap( info, bits, src, format, &src_pixmap, &src_pict, &use_repeat );
2101     if (!ret)
2102     {
2103         double xscale, yscale;
2104
2105         if (!use_repeat)
2106         {
2107             xscale = src->width / (double)dst->width;
2108             yscale = src->height / (double)dst->height;
2109         }
2110         else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2111
2112         dst_pict = get_xrender_picture( physdev, 0, &dst->visrect );
2113
2114         EnterCriticalSection( &xrender_cs );
2115         mask_pict = get_mask_pict( func.SourceConstantAlpha * 257 );
2116
2117         xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2118                       src->x, src->y, src->width, src->height,
2119                       physdev->x11dev->dc_rect.left + dst->x,
2120                       physdev->x11dev->dc_rect.top + dst->y,
2121                       dst->width, dst->height, xscale, yscale );
2122
2123         pXRenderFreePicture( gdi_display, src_pict );
2124         XFreePixmap( gdi_display, src_pixmap );
2125
2126         LeaveCriticalSection( &xrender_cs );
2127         add_device_bounds( physdev->x11dev, &dst->visrect );
2128     }
2129     return ret;
2130
2131 update_format:
2132     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2133     set_color_info( physdev->pict_format, info );
2134     return ERROR_BAD_FORMAT;
2135 }
2136
2137
2138 /***********************************************************************
2139  *           xrenderdrv_AlphaBlend
2140  */
2141 static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
2142                                    PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2143 {
2144     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2145     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2146     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2147     XRenderPictureAttributes pa;
2148     Pixmap tmp_pixmap = 0;
2149     double xscale, yscale;
2150
2151     if (src_dev->funcs != dst_dev->funcs)
2152     {
2153         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pAlphaBlend );
2154         return dst_dev->funcs->pAlphaBlend( dst_dev, dst, src_dev, src, blendfn );
2155     }
2156
2157     if ((blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->format != WXR_FORMAT_A8R8G8B8)
2158     {
2159         SetLastError( ERROR_INVALID_PARAMETER );
2160         return FALSE;
2161     }
2162
2163     dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
2164
2165     xscale = src->width / (double)dst->width;
2166     yscale = src->height / (double)dst->height;
2167
2168     src_pict = get_xrender_picture_source( physdev_src, FALSE );
2169
2170     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2171     {
2172         /* mono -> color blending needs an intermediate color pixmap */
2173         XRenderColor fg, bg;
2174         int width = src->visrect.right - src->visrect.left;
2175         int height = src->visrect.bottom - src->visrect.top;
2176
2177         /* blending doesn't use the destination DC colors */
2178         fg.red = fg.green = fg.blue = 0;
2179         bg.red = bg.green = bg.blue = 0xffff;
2180         fg.alpha = bg.alpha = 0xffff;
2181
2182         tmp_pixmap = XCreatePixmap( gdi_display, root_window, width, height,
2183                                     physdev_dst->pict_format->depth );
2184         tmp_pict = pXRenderCreatePicture( gdi_display, tmp_pixmap, physdev_dst->pict_format, 0, NULL );
2185
2186         xrender_mono_blit( src_pict, tmp_pict, physdev_dst->format, &fg, &bg,
2187                            src->visrect.left, src->visrect.top, width, height, 0, 0, width, height, 1, 1 );
2188     }
2189     else if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->pict_format)
2190     {
2191         /* we need a source picture with no alpha */
2192         enum wxr_format format = get_format_without_alpha( physdev_src->format );
2193         if (format != physdev_src->format)
2194         {
2195             pa.subwindow_mode = IncludeInferiors;
2196             tmp_pict = pXRenderCreatePicture( gdi_display, physdev_src->x11dev->drawable,
2197                                               pict_formats[format], CPSubwindowMode, &pa );
2198         }
2199     }
2200
2201     if (tmp_pict) src_pict = tmp_pict;
2202
2203     EnterCriticalSection( &xrender_cs );
2204     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2205
2206     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2207                   physdev_src->x11dev->dc_rect.left + src->x,
2208                   physdev_src->x11dev->dc_rect.top + src->y,
2209                   src->width, src->height,
2210                   physdev_dst->x11dev->dc_rect.left + dst->x,
2211                   physdev_dst->x11dev->dc_rect.top + dst->y,
2212                   dst->width, dst->height, xscale, yscale );
2213
2214     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2215     if (tmp_pixmap) XFreePixmap( gdi_display, tmp_pixmap );
2216
2217     LeaveCriticalSection( &xrender_cs );
2218     add_device_bounds( physdev_dst->x11dev, &dst->visrect );
2219     return TRUE;
2220 }
2221
2222 /***********************************************************************
2223  *           xrenderdrv_GradientFill
2224  */
2225 static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
2226                                      void * grad_array, ULONG ngrad, ULONG mode )
2227 {
2228 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
2229     static const XFixed stops[2] = { 0, 1 << 16 };
2230     struct xrender_physdev *physdev = get_xrender_dev( dev );
2231     XLinearGradient gradient;
2232     XRenderColor colors[2];
2233     Picture src_pict, dst_pict;
2234     unsigned int i;
2235     const GRADIENT_RECT *rect = grad_array;
2236     RECT rc;
2237     POINT pt[2];
2238
2239     if (!pXRenderCreateLinearGradient) goto fallback;
2240
2241     /* <= 16-bpp uses dithering */
2242     if (!physdev->pict_format || physdev->pict_format->depth <= 16) goto fallback;
2243
2244     switch (mode)
2245     {
2246     case GRADIENT_FILL_RECT_H:
2247     case GRADIENT_FILL_RECT_V:
2248         for (i = 0; i < ngrad; i++, rect++)
2249         {
2250             const TRIVERTEX *v1 = vert_array + rect->UpperLeft;
2251             const TRIVERTEX *v2 = vert_array + rect->LowerRight;
2252
2253             colors[0].red   = v1->Red * 257 / 256;
2254             colors[0].green = v1->Green * 257 / 256;
2255             colors[0].blue  = v1->Blue * 257 / 256;
2256             colors[1].red   = v2->Red * 257 / 256;
2257             colors[1].green = v2->Green * 257 / 256;
2258             colors[1].blue  = v2->Blue * 257 / 256;
2259             /* always ignore alpha since otherwise xrender will want to pre-multiply the colors */
2260             colors[0].alpha = colors[1].alpha = 65535;
2261
2262             pt[0].x = v1->x;
2263             pt[0].y = v1->y;
2264             pt[1].x = v2->x;
2265             pt[1].y = v2->y;
2266             LPtoDP( dev->hdc, pt, 2 );
2267             if (mode == GRADIENT_FILL_RECT_H)
2268             {
2269                 gradient.p1.y = gradient.p2.y = 0;
2270                 if (pt[1].x > pt[0].x)
2271                 {
2272                     gradient.p1.x = 0;
2273                     gradient.p2.x = (pt[1].x - pt[0].x) << 16;
2274                 }
2275                 else
2276                 {
2277                     gradient.p1.x = (pt[0].x - pt[1].x) << 16;
2278                     gradient.p2.x = 0;
2279                 }
2280             }
2281             else
2282             {
2283                 gradient.p1.x = gradient.p2.x = 0;
2284                 if (pt[1].y > pt[0].y)
2285                 {
2286                     gradient.p1.y = 0;
2287                     gradient.p2.y = (pt[1].y - pt[0].y) << 16;
2288                 }
2289                 else
2290                 {
2291                     gradient.p1.y = (pt[0].y - pt[1].y) << 16;
2292                     gradient.p2.y = 0;
2293                 }
2294             }
2295
2296             rc.left   = min( pt[0].x, pt[1].x );
2297             rc.top    = min( pt[0].y, pt[1].y );
2298             rc.right  = max( pt[0].x, pt[1].x );
2299             rc.bottom = max( pt[0].y, pt[1].y );
2300
2301             TRACE( "%u gradient %s colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n",
2302                    mode, wine_dbgstr_rect( &rc ),
2303                    colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha,
2304                    colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha );
2305
2306             dst_pict = get_xrender_picture( physdev, 0, NULL );
2307
2308             src_pict = pXRenderCreateLinearGradient( gdi_display, &gradient, stops, colors, 2 );
2309             xrender_blit( PictOpSrc, src_pict, 0, dst_pict,
2310                           0, 0, rc.right - rc.left, rc.bottom - rc.top,
2311                           physdev->x11dev->dc_rect.left + rc.left,
2312                           physdev->x11dev->dc_rect.top + rc.top,
2313                           rc.right - rc.left, rc.bottom - rc.top, 1, 1 );
2314             pXRenderFreePicture( gdi_display, src_pict );
2315             add_device_bounds( physdev->x11dev, &rc );
2316         }
2317         return TRUE;
2318     }
2319
2320 fallback:
2321 #endif
2322     dev = GET_NEXT_PHYSDEV( dev, pGradientFill );
2323     return dev->funcs->pGradientFill( dev, vert_array, nvert, grad_array, ngrad, mode );
2324 }
2325
2326 /***********************************************************************
2327  *           xrenderdrv_SelectBrush
2328  */
2329 static HBRUSH xrenderdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern )
2330 {
2331     struct xrender_physdev *physdev = get_xrender_dev( dev );
2332     Pixmap pixmap;
2333     XVisualInfo vis;
2334     XRenderPictFormat *format = physdev->pict_format;
2335
2336     if (!pattern) goto x11drv_fallback;
2337     if (pattern->info->bmiHeader.biBitCount == 1) goto x11drv_fallback;
2338     if (physdev->format == WXR_FORMAT_MONO) goto x11drv_fallback;
2339
2340     memset( &vis, 0, sizeof(vis) );
2341     vis.depth      = format->depth;
2342     vis.red_mask   = format->direct.redMask   << format->direct.red;
2343     vis.green_mask = format->direct.greenMask << format->direct.green;
2344     vis.blue_mask  = format->direct.blueMask  << format->direct.blue;
2345
2346     pixmap = create_pixmap_from_image( physdev->dev.hdc, &vis, pattern->info,
2347                                        &pattern->bits, pattern->usage );
2348     if (!pixmap) return 0;
2349
2350     if (physdev->x11dev->brush.pixmap) XFreePixmap( gdi_display, physdev->x11dev->brush.pixmap );
2351     physdev->x11dev->brush.pixmap = pixmap;
2352     physdev->x11dev->brush.fillStyle = FillTiled;
2353     physdev->x11dev->brush.pixel = 0;  /* ignored */
2354     physdev->x11dev->brush.style = BS_PATTERN;
2355     return hbrush;
2356
2357 x11drv_fallback:
2358     dev = GET_NEXT_PHYSDEV( dev, pSelectBrush );
2359     return dev->funcs->pSelectBrush( dev, hbrush, pattern );
2360 }
2361
2362
2363 static const struct gdi_dc_funcs xrender_funcs =
2364 {
2365     NULL,                               /* pAbortDoc */
2366     NULL,                               /* pAbortPath */
2367     xrenderdrv_AlphaBlend,              /* pAlphaBlend */
2368     NULL,                               /* pAngleArc */
2369     NULL,                               /* pArc */
2370     NULL,                               /* pArcTo */
2371     NULL,                               /* pBeginPath */
2372     xrenderdrv_BlendImage,              /* pBlendImage */
2373     NULL,                               /* pChord */
2374     NULL,                               /* pCloseFigure */
2375     xrenderdrv_CreateCompatibleDC,      /* pCreateCompatibleDC */
2376     xrenderdrv_CreateDC,                /* pCreateDC */
2377     xrenderdrv_DeleteDC,                /* pDeleteDC */
2378     NULL,                               /* pDeleteObject */
2379     NULL,                               /* pDeviceCapabilities */
2380     NULL,                               /* pEllipse */
2381     NULL,                               /* pEndDoc */
2382     NULL,                               /* pEndPage */
2383     NULL,                               /* pEndPath */
2384     NULL,                               /* pEnumFonts */
2385     NULL,                               /* pEnumICMProfiles */
2386     NULL,                               /* pExcludeClipRect */
2387     NULL,                               /* pExtDeviceMode */
2388     xrenderdrv_ExtEscape,               /* pExtEscape */
2389     NULL,                               /* pExtFloodFill */
2390     NULL,                               /* pExtSelectClipRgn */
2391     xrenderdrv_ExtTextOut,              /* pExtTextOut */
2392     NULL,                               /* pFillPath */
2393     NULL,                               /* pFillRgn */
2394     NULL,                               /* pFlattenPath */
2395     NULL,                               /* pFontIsLinked */
2396     NULL,                               /* pFrameRgn */
2397     NULL,                               /* pGdiComment */
2398     NULL,                               /* pGdiRealizationInfo */
2399     NULL,                               /* pGetBoundsRect */
2400     NULL,                               /* pGetCharABCWidths */
2401     NULL,                               /* pGetCharABCWidthsI */
2402     NULL,                               /* pGetCharWidth */
2403     NULL,                               /* pGetDeviceCaps */
2404     NULL,                               /* pGetDeviceGammaRamp */
2405     NULL,                               /* pGetFontData */
2406     NULL,                               /* pGetFontUnicodeRanges */
2407     NULL,                               /* pGetGlyphIndices */
2408     NULL,                               /* pGetGlyphOutline */
2409     NULL,                               /* pGetICMProfile */
2410     NULL,                               /* pGetImage */
2411     NULL,                               /* pGetKerningPairs */
2412     NULL,                               /* pGetNearestColor */
2413     NULL,                               /* pGetOutlineTextMetrics */
2414     NULL,                               /* pGetPixel */
2415     NULL,                               /* pGetSystemPaletteEntries */
2416     NULL,                               /* pGetTextCharsetInfo */
2417     NULL,                               /* pGetTextExtentExPoint */
2418     NULL,                               /* pGetTextExtentExPointI */
2419     NULL,                               /* pGetTextFace */
2420     NULL,                               /* pGetTextMetrics */
2421     xrenderdrv_GradientFill,            /* pGradientFill */
2422     NULL,                               /* pIntersectClipRect */
2423     NULL,                               /* pInvertRgn */
2424     NULL,                               /* pLineTo */
2425     NULL,                               /* pModifyWorldTransform */
2426     NULL,                               /* pMoveTo */
2427     NULL,                               /* pOffsetClipRgn */
2428     NULL,                               /* pOffsetViewportOrg */
2429     NULL,                               /* pOffsetWindowOrg */
2430     NULL,                               /* pPaintRgn */
2431     NULL,                               /* pPatBlt */
2432     NULL,                               /* pPie */
2433     NULL,                               /* pPolyBezier */
2434     NULL,                               /* pPolyBezierTo */
2435     NULL,                               /* pPolyDraw */
2436     NULL,                               /* pPolyPolygon */
2437     NULL,                               /* pPolyPolyline */
2438     NULL,                               /* pPolygon */
2439     NULL,                               /* pPolyline */
2440     NULL,                               /* pPolylineTo */
2441     xrenderdrv_PutImage,                /* pPutImage */
2442     NULL,                               /* pRealizeDefaultPalette */
2443     NULL,                               /* pRealizePalette */
2444     NULL,                               /* pRectangle */
2445     NULL,                               /* pResetDC */
2446     NULL,                               /* pRestoreDC */
2447     NULL,                               /* pRoundRect */
2448     NULL,                               /* pSaveDC */
2449     NULL,                               /* pScaleViewportExt */
2450     NULL,                               /* pScaleWindowExt */
2451     NULL,                               /* pSelectBitmap */
2452     xrenderdrv_SelectBrush,             /* pSelectBrush */
2453     NULL,                               /* pSelectClipPath */
2454     xrenderdrv_SelectFont,              /* pSelectFont */
2455     NULL,                               /* pSelectPalette */
2456     NULL,                               /* pSelectPen */
2457     NULL,                               /* pSetArcDirection */
2458     NULL,                               /* pSetBkColor */
2459     NULL,                               /* pSetBkMode */
2460     NULL,                               /* pSetBoundsRect */
2461     NULL,                               /* pSetDCBrushColor */
2462     NULL,                               /* pSetDCPenColor */
2463     NULL,                               /* pSetDIBitsToDevice */
2464     xrenderdrv_SetDeviceClipping,       /* pSetDeviceClipping */
2465     NULL,                               /* pSetDeviceGammaRamp */
2466     NULL,                               /* pSetLayout */
2467     NULL,                               /* pSetMapMode */
2468     NULL,                               /* pSetMapperFlags */
2469     NULL,                               /* pSetPixel */
2470     NULL,                               /* pSetPolyFillMode */
2471     NULL,                               /* pSetROP2 */
2472     NULL,                               /* pSetRelAbs */
2473     NULL,                               /* pSetStretchBltMode */
2474     NULL,                               /* pSetTextAlign */
2475     NULL,                               /* pSetTextCharacterExtra */
2476     NULL,                               /* pSetTextColor */
2477     NULL,                               /* pSetTextJustification */
2478     NULL,                               /* pSetViewportExt */
2479     NULL,                               /* pSetViewportOrg */
2480     NULL,                               /* pSetWindowExt */
2481     NULL,                               /* pSetWindowOrg */
2482     NULL,                               /* pSetWorldTransform */
2483     NULL,                               /* pStartDoc */
2484     NULL,                               /* pStartPage */
2485     xrenderdrv_StretchBlt,              /* pStretchBlt */
2486     NULL,                               /* pStretchDIBits */
2487     NULL,                               /* pStrokeAndFillPath */
2488     NULL,                               /* pStrokePath */
2489     NULL,                               /* pUnrealizePalette */
2490     NULL,                               /* pWidenPath */
2491     NULL,                               /* wine_get_wgl_driver */
2492     GDI_PRIORITY_GRAPHICS_DRV + 10      /* priority */
2493 };
2494
2495 #else /* SONAME_LIBXRENDER */
2496
2497 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
2498 {
2499     TRACE("XRender support not compiled in.\n");
2500     return NULL;
2501 }
2502
2503 #endif /* SONAME_LIBXRENDER */