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