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