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