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