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