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