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