msxml3: Skip leading space characters when loading from BSTR.
[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     X11DRV_LockDIBSection( physdev_dst->x11dev, DIB_Status_GdiMod );
2196     if (physdev_dst != physdev_src) X11DRV_LockDIBSection( physdev_src->x11dev, DIB_Status_GdiMod );
2197
2198     if (rop != SRCCOPY)
2199     {
2200         GC tmpGC;
2201         Pixmap tmp_pixmap;
2202         struct bitblt_coords tmp;
2203
2204         /* make coordinates relative to tmp pixmap */
2205         tmp = *dst;
2206         tmp.x -= tmp.visrect.left;
2207         tmp.y -= tmp.visrect.top;
2208         OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2209
2210         wine_tsx11_lock();
2211         tmpGC = XCreateGC( gdi_display, physdev_dst->x11dev->drawable, 0, NULL );
2212         XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
2213         XSetGraphicsExposures( gdi_display, tmpGC, False );
2214         tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2215                                     tmp.visrect.bottom - tmp.visrect.top, physdev_dst->x11dev->depth );
2216         wine_tsx11_unlock();
2217
2218         xrender_stretch_blit( physdev_src, physdev_dst, tmp_pixmap, src, &tmp );
2219         execute_rop( physdev_dst->x11dev, tmp_pixmap, tmpGC, &dst->visrect, rop );
2220
2221         wine_tsx11_lock();
2222         XFreePixmap( gdi_display, tmp_pixmap );
2223         XFreeGC( gdi_display, tmpGC );
2224         wine_tsx11_unlock();
2225     }
2226     else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
2227
2228     if (physdev_dst != physdev_src) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2229     X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2230     return TRUE;
2231
2232 x11drv_fallback:
2233     return X11DRV_StretchBlt( &physdev_dst->x11dev->dev, dst, &physdev_src->x11dev->dev, src, rop );
2234 }
2235
2236
2237 /***********************************************************************
2238  *           xrenderdrv_PutImage
2239  */
2240 static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
2241                                   const struct gdi_image_bits *bits, struct bitblt_coords *src,
2242                                   struct bitblt_coords *dst, DWORD rop )
2243 {
2244     struct xrender_physdev *physdev;
2245     X_PHYSBITMAP *bitmap;
2246     DWORD ret;
2247     Pixmap tmp_pixmap;
2248     GC gc;
2249     enum wxr_format src_format, dst_format;
2250     XRenderPictFormat *pict_format;
2251     Pixmap src_pixmap;
2252     Picture src_pict, mask_pict = 0;
2253     BOOL use_repeat;
2254
2255     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2256
2257     if (hbitmap)
2258     {
2259         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
2260         physdev = NULL;
2261         dst_format = get_xrender_format_from_color_shifts( bitmap->depth, &bitmap->color_shifts );
2262     }
2263     else
2264     {
2265         physdev = get_xrender_dev( dev );
2266         bitmap = NULL;
2267         dst_format = physdev->format;
2268     }
2269
2270     src_format = get_xrender_format_from_bitmapinfo( info );
2271     if (!(pict_format = pict_formats[src_format])) goto update_format;
2272
2273     /* make sure we can create an image with the same bpp */
2274     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2275         goto update_format;
2276
2277     /* mono <-> color conversions not supported */
2278     if ((src_format != dst_format) && (src_format == WXR_FORMAT_MONO || dst_format == WXR_FORMAT_MONO))
2279         goto x11drv_fallback;
2280
2281     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2282
2283     if (!has_alpha( src_format ) && has_alpha( dst_format )) mask_pict = get_no_alpha_mask();
2284
2285     ret = create_image_pixmap( info, bits, src, src_format, &src_pixmap, &src_pict, &use_repeat );
2286     if (!ret)
2287     {
2288         struct bitblt_coords tmp;
2289
2290         if (bitmap)
2291         {
2292             HRGN rgn = CreateRectRgnIndirect( &dst->visrect );
2293             if (clip) CombineRgn( rgn, rgn, clip, RGN_AND );
2294
2295             X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
2296
2297             xrender_put_image( src_pixmap, src_pict, mask_pict, rgn,
2298                                pict_formats[dst_format], NULL, bitmap->pixmap, src, dst, use_repeat );
2299
2300             X11DRV_DIB_Unlock( bitmap, TRUE );
2301             DeleteObject( rgn );
2302         }
2303         else
2304         {
2305             X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
2306
2307             if (rop != SRCCOPY)
2308             {
2309                 BOOL restore_region = add_extra_clipping_region( physdev->x11dev, clip );
2310
2311                 /* make coordinates relative to tmp pixmap */
2312                 tmp = *dst;
2313                 tmp.x -= tmp.visrect.left;
2314                 tmp.y -= tmp.visrect.top;
2315                 OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2316
2317                 wine_tsx11_lock();
2318                 gc = XCreateGC( gdi_display, physdev->x11dev->drawable, 0, NULL );
2319                 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
2320                 XSetGraphicsExposures( gdi_display, gc, False );
2321                 tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2322                                             tmp.visrect.bottom - tmp.visrect.top, physdev->x11dev->depth );
2323                 wine_tsx11_unlock();
2324
2325                 xrender_put_image( src_pixmap, src_pict, mask_pict, NULL, physdev->pict_format,
2326                                    NULL, tmp_pixmap, src, &tmp, use_repeat );
2327                 execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
2328
2329                 wine_tsx11_lock();
2330                 XFreePixmap( gdi_display, tmp_pixmap );
2331                 XFreeGC( gdi_display, gc );
2332                 wine_tsx11_unlock();
2333
2334                 if (restore_region) restore_clipping_region( physdev->x11dev );
2335             }
2336             else xrender_put_image( src_pixmap, src_pict, mask_pict, clip,
2337                                     physdev->pict_format, physdev, 0, src, dst, use_repeat );
2338
2339             X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2340         }
2341
2342         wine_tsx11_lock();
2343         pXRenderFreePicture( gdi_display, src_pict );
2344         XFreePixmap( gdi_display, src_pixmap );
2345         wine_tsx11_unlock();
2346     }
2347     return ret;
2348
2349 update_format:
2350     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2351     set_color_info( pict_formats[dst_format], info );
2352     return ERROR_BAD_FORMAT;
2353
2354 x11drv_fallback:
2355     if (hbitmap) return X11DRV_PutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
2356     dev = GET_NEXT_PHYSDEV( dev, pPutImage );
2357     return dev->funcs->pPutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
2358 }
2359
2360
2361 /***********************************************************************
2362  *           xrenderdrv_BlendImage
2363  */
2364 static DWORD xrenderdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits,
2365                                     struct bitblt_coords *src, struct bitblt_coords *dst,
2366                                     BLENDFUNCTION func )
2367 {
2368     struct xrender_physdev *physdev = get_xrender_dev( dev );
2369     DWORD ret;
2370     enum wxr_format format;
2371     XRenderPictFormat *pict_format;
2372     Picture dst_pict, src_pict, mask_pict;
2373     Pixmap src_pixmap;
2374     BOOL use_repeat;
2375
2376     if (!X11DRV_XRender_Installed)
2377     {
2378         dev = GET_NEXT_PHYSDEV( dev, pBlendImage );
2379         return dev->funcs->pBlendImage( dev, info, bits, src, dst, func );
2380     }
2381
2382     format = get_xrender_format_from_bitmapinfo( info );
2383     if (!(func.AlphaFormat & AC_SRC_ALPHA))
2384         format = get_format_without_alpha( format );
2385     else if (format != WXR_FORMAT_A8R8G8B8)
2386         return ERROR_INVALID_PARAMETER;
2387
2388     if (!(pict_format = pict_formats[format])) goto update_format;
2389
2390     /* make sure we can create an image with the same bpp */
2391     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2392         goto update_format;
2393
2394     if (format == WXR_FORMAT_MONO && physdev->format != WXR_FORMAT_MONO)
2395         goto update_format;
2396
2397     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2398
2399     ret = create_image_pixmap( info, bits, src, format, &src_pixmap, &src_pict, &use_repeat );
2400     if (!ret)
2401     {
2402         double xscale, yscale;
2403
2404         X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
2405
2406         if (!use_repeat)
2407         {
2408             xscale = src->width / (double)dst->width;
2409             yscale = src->height / (double)dst->height;
2410         }
2411         else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2412
2413         dst_pict = get_xrender_picture( physdev, 0, &dst->visrect );
2414
2415         EnterCriticalSection( &xrender_cs );
2416         mask_pict = get_mask_pict( func.SourceConstantAlpha * 257 );
2417
2418         xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict, src->x, src->y,
2419                       physdev->x11dev->dc_rect.left + dst->x,
2420                       physdev->x11dev->dc_rect.top + dst->y,
2421                       xscale, yscale, dst->width, dst->height );
2422
2423         wine_tsx11_lock();
2424         pXRenderFreePicture( gdi_display, src_pict );
2425         XFreePixmap( gdi_display, src_pixmap );
2426         wine_tsx11_unlock();
2427
2428         LeaveCriticalSection( &xrender_cs );
2429
2430         X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2431     }
2432     return ret;
2433
2434 update_format:
2435     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2436     set_color_info( physdev->pict_format, info );
2437     return ERROR_BAD_FORMAT;
2438 }
2439
2440
2441 /***********************************************************************
2442  *           xrenderdrv_AlphaBlend
2443  */
2444 static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
2445                                    PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2446 {
2447     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2448     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2449     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2450     XRenderPictureAttributes pa;
2451     Pixmap tmp_pixmap = 0;
2452     double xscale, yscale;
2453     BOOL use_repeat;
2454
2455     if (!X11DRV_XRender_Installed || src_dev->funcs != dst_dev->funcs)
2456     {
2457         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pAlphaBlend );
2458         return dst_dev->funcs->pAlphaBlend( dst_dev, dst, src_dev, src, blendfn );
2459     }
2460
2461     if ((blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->format != WXR_FORMAT_A8R8G8B8)
2462     {
2463         SetLastError( ERROR_INVALID_PARAMETER );
2464         return FALSE;
2465     }
2466
2467     X11DRV_LockDIBSection( physdev_dst->x11dev, DIB_Status_GdiMod );
2468     if (physdev_dst != physdev_src) X11DRV_LockDIBSection( physdev_src->x11dev, DIB_Status_GdiMod );
2469
2470     dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
2471
2472     use_repeat = use_source_repeat( physdev_src );
2473     if (!use_repeat)
2474     {
2475         xscale = src->width / (double)dst->width;
2476         yscale = src->height / (double)dst->height;
2477     }
2478     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2479
2480     src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2481
2482     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2483     {
2484         /* mono -> color blending needs an intermediate color pixmap */
2485         XRenderColor fg, bg;
2486         int width = src->visrect.right - src->visrect.left;
2487         int height = src->visrect.bottom - src->visrect.top;
2488
2489         /* blending doesn't use the destination DC colors */
2490         fg.red = fg.green = fg.blue = 0;
2491         bg.red = bg.green = bg.blue = 0xffff;
2492         fg.alpha = bg.alpha = 0xffff;
2493
2494         wine_tsx11_lock();
2495         tmp_pixmap = XCreatePixmap( gdi_display, root_window, width, height,
2496                                     physdev_dst->pict_format->depth );
2497         pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2498         tmp_pict = pXRenderCreatePicture( gdi_display, tmp_pixmap, physdev_dst->pict_format,
2499                                           CPRepeat, &pa );
2500         wine_tsx11_unlock();
2501
2502         xrender_mono_blit( src_pict, tmp_pict, physdev_dst->format, &fg, &bg,
2503                            src->visrect.left, src->visrect.top, 0, 0, 1, 1, width, height );
2504     }
2505     else if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->pict_format)
2506     {
2507         /* we need a source picture with no alpha */
2508         enum wxr_format format = get_format_without_alpha( physdev_src->format );
2509         if (format != physdev_src->format)
2510         {
2511             wine_tsx11_lock();
2512             pa.subwindow_mode = IncludeInferiors;
2513             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2514             tmp_pict = pXRenderCreatePicture( gdi_display, physdev_src->x11dev->drawable,
2515                                               pict_formats[format], CPSubwindowMode|CPRepeat, &pa );
2516             wine_tsx11_unlock();
2517         }
2518     }
2519
2520     if (tmp_pict) src_pict = tmp_pict;
2521
2522     EnterCriticalSection( &xrender_cs );
2523     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2524
2525     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2526                   physdev_src->x11dev->dc_rect.left + src->x,
2527                   physdev_src->x11dev->dc_rect.top + src->y,
2528                   physdev_dst->x11dev->dc_rect.left + dst->x,
2529                   physdev_dst->x11dev->dc_rect.top + dst->y,
2530                   xscale, yscale, dst->width, dst->height );
2531
2532     wine_tsx11_lock();
2533     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2534     if (tmp_pixmap) XFreePixmap( gdi_display, tmp_pixmap );
2535     wine_tsx11_unlock();
2536
2537     LeaveCriticalSection( &xrender_cs );
2538     if (physdev_src != physdev_dst) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2539     X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2540     return TRUE;
2541 }
2542
2543 /***********************************************************************
2544  *           xrenderdrv_GradientFill
2545  */
2546 static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
2547                                      void * grad_array, ULONG ngrad, ULONG mode )
2548 {
2549 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
2550     static const XFixed stops[2] = { 0, 1 << 16 };
2551     struct xrender_physdev *physdev = get_xrender_dev( dev );
2552     XLinearGradient gradient;
2553     XRenderColor colors[2];
2554     Picture src_pict, dst_pict;
2555     unsigned int i;
2556     const GRADIENT_RECT *rect = grad_array;
2557     POINT pt[2];
2558
2559     if (!X11DRV_XRender_Installed) goto fallback;
2560     if (!pXRenderCreateLinearGradient) goto fallback;
2561
2562     /* <= 16-bpp uses dithering */
2563     if (!physdev->pict_format || physdev->pict_format->depth <= 16) goto fallback;
2564
2565     switch (mode)
2566     {
2567     case GRADIENT_FILL_RECT_H:
2568     case GRADIENT_FILL_RECT_V:
2569         X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
2570         for (i = 0; i < ngrad; i++, rect++)
2571         {
2572             const TRIVERTEX *v1 = vert_array + rect->UpperLeft;
2573             const TRIVERTEX *v2 = vert_array + rect->LowerRight;
2574
2575             colors[0].red   = v1->Red * 257 / 256;
2576             colors[0].green = v1->Green * 257 / 256;
2577             colors[0].blue  = v1->Blue * 257 / 256;
2578             colors[1].red   = v2->Red * 257 / 256;
2579             colors[1].green = v2->Green * 257 / 256;
2580             colors[1].blue  = v2->Blue * 257 / 256;
2581             /* always ignore alpha since otherwise xrender will want to pre-multiply the colors */
2582             colors[0].alpha = colors[1].alpha = 65535;
2583
2584             pt[0].x = v1->x;
2585             pt[0].y = v1->y;
2586             pt[1].x = v2->x;
2587             pt[1].y = v2->y;
2588             LPtoDP( dev->hdc, pt, 2 );
2589             if (mode == GRADIENT_FILL_RECT_H)
2590             {
2591                 gradient.p1.y = gradient.p2.y = 0;
2592                 if (pt[1].x > pt[0].x)
2593                 {
2594                     gradient.p1.x = 0;
2595                     gradient.p2.x = (pt[1].x - pt[0].x) << 16;
2596                 }
2597                 else
2598                 {
2599                     gradient.p1.x = (pt[0].x - pt[1].x) << 16;
2600                     gradient.p2.x = 0;
2601                 }
2602             }
2603             else
2604             {
2605                 gradient.p1.x = gradient.p2.x = 0;
2606                 if (pt[1].y > pt[0].y)
2607                 {
2608                     gradient.p1.y = 0;
2609                     gradient.p2.y = (pt[1].y - pt[0].y) << 16;
2610                 }
2611                 else
2612                 {
2613                     gradient.p1.y = (pt[0].y - pt[1].y) << 16;
2614                     gradient.p2.y = 0;
2615                 }
2616             }
2617
2618             TRACE( "%u gradient %d,%d - %d,%d colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n",
2619                    mode, pt[0].x, pt[0].y, pt[1].x, pt[1].y,
2620                    colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha,
2621                    colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha );
2622
2623             dst_pict = get_xrender_picture( physdev, 0, NULL );
2624
2625             wine_tsx11_lock();
2626             src_pict = pXRenderCreateLinearGradient( gdi_display, &gradient, stops, colors, 2 );
2627             xrender_blit( PictOpSrc, src_pict, 0, dst_pict, 0, 0,
2628                           physdev->x11dev->dc_rect.left + min( pt[0].x, pt[1].x ),
2629                           physdev->x11dev->dc_rect.top + min( pt[0].y, pt[1].y ),
2630                           1, 1, abs(pt[1].x - pt[0].x), abs(pt[1].y - pt[0].y) );
2631             pXRenderFreePicture( gdi_display, src_pict );
2632             wine_tsx11_unlock();
2633         }
2634         X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2635         return TRUE;
2636     }
2637
2638 fallback:
2639 #endif
2640     dev = GET_NEXT_PHYSDEV( dev, pGradientFill );
2641     return dev->funcs->pGradientFill( dev, vert_array, nvert, grad_array, ngrad, mode );
2642 }
2643
2644 /***********************************************************************
2645  *           xrenderdrv_SelectBrush
2646  */
2647 static HBRUSH xrenderdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, HBITMAP bitmap,
2648                                       const BITMAPINFO *info, void *bits, UINT usage )
2649 {
2650     struct xrender_physdev *physdev = get_xrender_dev( dev );
2651     X_PHYSBITMAP *physbitmap;
2652     enum wxr_format format;
2653     BOOL delete_bitmap = FALSE;
2654     BITMAP bm;
2655     Pixmap pixmap;
2656     Picture src_pict, dst_pict;
2657     XRenderPictureAttributes pa;
2658
2659     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2660     if (!bitmap && !info) goto x11drv_fallback;
2661     if (physdev->format == WXR_FORMAT_MONO) goto x11drv_fallback;
2662
2663     if (!bitmap || !(physbitmap = X11DRV_get_phys_bitmap( bitmap )))
2664     {
2665         if (!(bitmap = create_brush_bitmap( physdev->x11dev, info, bits, usage ))) return 0;
2666         physbitmap = X11DRV_get_phys_bitmap( bitmap );
2667         delete_bitmap = TRUE;
2668     }
2669
2670     format = get_xrender_format_from_color_shifts( physbitmap->depth, &physbitmap->color_shifts );
2671     if (format == WXR_FORMAT_MONO || !pict_formats[format]) goto x11drv_fallback;
2672
2673     GetObjectW( bitmap, sizeof(bm), &bm );
2674
2675     X11DRV_DIB_Lock( physbitmap, DIB_Status_GdiMod );
2676
2677     wine_tsx11_lock();
2678     pixmap = XCreatePixmap( gdi_display, root_window, bm.bmWidth, bm.bmHeight,
2679                             physdev->pict_format->depth );
2680
2681     pa.repeat = RepeatNone;
2682     src_pict = pXRenderCreatePicture(gdi_display, physbitmap->pixmap, pict_formats[format], CPRepeat, &pa);
2683     dst_pict = pXRenderCreatePicture(gdi_display, pixmap, physdev->pict_format, CPRepeat, &pa);
2684
2685     xrender_blit( PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, bm.bmWidth, bm.bmHeight );
2686     pXRenderFreePicture( gdi_display, src_pict );
2687     pXRenderFreePicture( gdi_display, dst_pict );
2688
2689     if (physdev->x11dev->brush.pixmap) XFreePixmap( gdi_display, physdev->x11dev->brush.pixmap );
2690     physdev->x11dev->brush.pixmap = pixmap;
2691     physdev->x11dev->brush.fillStyle = FillTiled;
2692     physdev->x11dev->brush.pixel = 0;  /* ignored */
2693     physdev->x11dev->brush.style = BS_PATTERN;
2694     wine_tsx11_unlock();
2695
2696     X11DRV_DIB_Unlock( physbitmap, TRUE );
2697     if (delete_bitmap) DeleteObject( bitmap );
2698     return hbrush;
2699
2700 x11drv_fallback:
2701     if (delete_bitmap) DeleteObject( bitmap );
2702     dev = GET_NEXT_PHYSDEV( dev, pSelectBrush );
2703     return dev->funcs->pSelectBrush( dev, hbrush, bitmap, info, bits, usage );
2704 }
2705
2706
2707 static const struct gdi_dc_funcs xrender_funcs =
2708 {
2709     NULL,                               /* pAbortDoc */
2710     NULL,                               /* pAbortPath */
2711     xrenderdrv_AlphaBlend,              /* pAlphaBlend */
2712     NULL,                               /* pAngleArc */
2713     NULL,                               /* pArc */
2714     NULL,                               /* pArcTo */
2715     NULL,                               /* pBeginPath */
2716     xrenderdrv_BlendImage,              /* pBlendImage */
2717     NULL,                               /* pChoosePixelFormat */
2718     NULL,                               /* pChord */
2719     NULL,                               /* pCloseFigure */
2720     xrenderdrv_CopyBitmap,              /* pCopyBitmap */
2721     xrenderdrv_CreateBitmap,            /* pCreateBitmap */
2722     xrenderdrv_CreateCompatibleDC,      /* pCreateCompatibleDC */
2723     xrenderdrv_CreateDC,                /* pCreateDC */
2724     NULL,                               /* pCreateDIBSection */
2725     xrenderdrv_DeleteBitmap,            /* pDeleteBitmap */
2726     xrenderdrv_DeleteDC,                /* pDeleteDC */
2727     NULL,                               /* pDeleteObject */
2728     NULL,                               /* pDescribePixelFormat */
2729     NULL,                               /* pDeviceCapabilities */
2730     NULL,                               /* pEllipse */
2731     NULL,                               /* pEndDoc */
2732     NULL,                               /* pEndPage */
2733     NULL,                               /* pEndPath */
2734     NULL,                               /* pEnumFonts */
2735     NULL,                               /* pEnumICMProfiles */
2736     NULL,                               /* pExcludeClipRect */
2737     NULL,                               /* pExtDeviceMode */
2738     xrenderdrv_ExtEscape,               /* pExtEscape */
2739     NULL,                               /* pExtFloodFill */
2740     NULL,                               /* pExtSelectClipRgn */
2741     xrenderdrv_ExtTextOut,              /* pExtTextOut */
2742     NULL,                               /* pFillPath */
2743     NULL,                               /* pFillRgn */
2744     NULL,                               /* pFlattenPath */
2745     NULL,                               /* pFontIsLinked */
2746     NULL,                               /* pFrameRgn */
2747     NULL,                               /* pGdiComment */
2748     NULL,                               /* pGdiRealizationInfo */
2749     NULL,                               /* pGetCharABCWidths */
2750     NULL,                               /* pGetCharABCWidthsI */
2751     NULL,                               /* pGetCharWidth */
2752     NULL,                               /* pGetDeviceCaps */
2753     NULL,                               /* pGetDeviceGammaRamp */
2754     NULL,                               /* pGetFontData */
2755     NULL,                               /* pGetFontUnicodeRanges */
2756     NULL,                               /* pGetGlyphIndices */
2757     NULL,                               /* pGetGlyphOutline */
2758     NULL,                               /* pGetICMProfile */
2759     xrenderdrv_GetImage,                /* pGetImage */
2760     NULL,                               /* pGetKerningPairs */
2761     NULL,                               /* pGetNearestColor */
2762     NULL,                               /* pGetOutlineTextMetrics */
2763     NULL,                               /* pGetPixel */
2764     NULL,                               /* pGetPixelFormat */
2765     NULL,                               /* pGetSystemPaletteEntries */
2766     NULL,                               /* pGetTextCharsetInfo */
2767     NULL,                               /* pGetTextExtentExPoint */
2768     NULL,                               /* pGetTextExtentExPointI */
2769     NULL,                               /* pGetTextFace */
2770     NULL,                               /* pGetTextMetrics */
2771     xrenderdrv_GradientFill,            /* pGradientFill */
2772     NULL,                               /* pIntersectClipRect */
2773     NULL,                               /* pInvertRgn */
2774     NULL,                               /* pLineTo */
2775     NULL,                               /* pModifyWorldTransform */
2776     NULL,                               /* pMoveTo */
2777     NULL,                               /* pOffsetClipRgn */
2778     NULL,                               /* pOffsetViewportOrg */
2779     NULL,                               /* pOffsetWindowOrg */
2780     NULL,                               /* pPaintRgn */
2781     NULL,                               /* pPatBlt */
2782     NULL,                               /* pPie */
2783     NULL,                               /* pPolyBezier */
2784     NULL,                               /* pPolyBezierTo */
2785     NULL,                               /* pPolyDraw */
2786     NULL,                               /* pPolyPolygon */
2787     NULL,                               /* pPolyPolyline */
2788     NULL,                               /* pPolygon */
2789     NULL,                               /* pPolyline */
2790     NULL,                               /* pPolylineTo */
2791     xrenderdrv_PutImage,                /* pPutImage */
2792     NULL,                               /* pRealizeDefaultPalette */
2793     NULL,                               /* pRealizePalette */
2794     NULL,                               /* pRectangle */
2795     NULL,                               /* pResetDC */
2796     NULL,                               /* pRestoreDC */
2797     NULL,                               /* pRoundRect */
2798     NULL,                               /* pSaveDC */
2799     NULL,                               /* pScaleViewportExt */
2800     NULL,                               /* pScaleWindowExt */
2801     xrenderdrv_SelectBitmap,            /* pSelectBitmap */
2802     xrenderdrv_SelectBrush,             /* pSelectBrush */
2803     NULL,                               /* pSelectClipPath */
2804     xrenderdrv_SelectFont,              /* pSelectFont */
2805     NULL,                               /* pSelectPalette */
2806     NULL,                               /* pSelectPen */
2807     NULL,                               /* pSetArcDirection */
2808     NULL,                               /* pSetBkColor */
2809     NULL,                               /* pSetBkMode */
2810     NULL,                               /* pSetDCBrushColor */
2811     NULL,                               /* pSetDCPenColor */
2812     NULL,                               /* pSetDIBColorTable */
2813     NULL,                               /* pSetDIBitsToDevice */
2814     xrenderdrv_SetDeviceClipping,       /* pSetDeviceClipping */
2815     NULL,                               /* pSetDeviceGammaRamp */
2816     NULL,                               /* pSetLayout */
2817     NULL,                               /* pSetMapMode */
2818     NULL,                               /* pSetMapperFlags */
2819     NULL,                               /* pSetPixel */
2820     NULL,                               /* pSetPixelFormat */
2821     NULL,                               /* pSetPolyFillMode */
2822     NULL,                               /* pSetROP2 */
2823     NULL,                               /* pSetRelAbs */
2824     NULL,                               /* pSetStretchBltMode */
2825     NULL,                               /* pSetTextAlign */
2826     NULL,                               /* pSetTextCharacterExtra */
2827     NULL,                               /* pSetTextColor */
2828     NULL,                               /* pSetTextJustification */
2829     NULL,                               /* pSetViewportExt */
2830     NULL,                               /* pSetViewportOrg */
2831     NULL,                               /* pSetWindowExt */
2832     NULL,                               /* pSetWindowOrg */
2833     NULL,                               /* pSetWorldTransform */
2834     NULL,                               /* pStartDoc */
2835     NULL,                               /* pStartPage */
2836     xrenderdrv_StretchBlt,              /* pStretchBlt */
2837     NULL,                               /* pStretchDIBits */
2838     NULL,                               /* pStrokeAndFillPath */
2839     NULL,                               /* pStrokePath */
2840     NULL,                               /* pSwapBuffers */
2841     NULL,                               /* pUnrealizePalette */
2842     NULL,                               /* pWidenPath */
2843     /* OpenGL not supported */
2844 };
2845
2846 #else /* SONAME_LIBXRENDER */
2847
2848 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
2849 {
2850     TRACE("XRender support not compiled in.\n");
2851     return NULL;
2852 }
2853
2854 void X11DRV_XRender_Finalize(void)
2855 {
2856 }
2857
2858 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2859 {
2860     return FALSE;
2861 }
2862
2863 #endif /* SONAME_LIBXRENDER */