winealsa: Fix AudioRenderClient Get/ReleaseBuffer protocol.
[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     if(physdev->x11dev->depth == 1) {
1755         if((physdev->x11dev->textPixel & 0xffffff) == 0) {
1756             textPixel = 0;
1757             backgroundPixel = 1;
1758         } else {
1759             textPixel = 1;
1760             backgroundPixel = 0;
1761         }
1762     } else {
1763         textPixel = physdev->x11dev->textPixel;
1764         backgroundPixel = physdev->x11dev->backgroundPixel;
1765     }
1766
1767     if(flags & ETO_OPAQUE)
1768     {
1769         wine_tsx11_lock();
1770         XSetForeground( gdi_display, physdev->x11dev->gc, backgroundPixel );
1771         XFillRectangle( gdi_display, physdev->x11dev->drawable, physdev->x11dev->gc,
1772                         physdev->x11dev->dc_rect.left + lprect->left, physdev->x11dev->dc_rect.top + lprect->top,
1773                         lprect->right - lprect->left, lprect->bottom - lprect->top );
1774         wine_tsx11_unlock();
1775     }
1776
1777     if(count == 0) return TRUE;
1778
1779     EnterCriticalSection(&xrender_cs);
1780
1781     entry = glyphsetCache + physdev->cache_index;
1782     aa_type = entry->aa_default;
1783     formatEntry = entry->format[aa_type];
1784
1785     for(idx = 0; idx < count; idx++) {
1786         if( !formatEntry ) {
1787             UploadGlyph(physdev, wstr[idx], aa_type);
1788             /* re-evaluate antialias since aa_default may have changed */
1789             aa_type = entry->aa_default;
1790             formatEntry = entry->format[aa_type];
1791         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1792             UploadGlyph(physdev, wstr[idx], aa_type);
1793         }
1794     }
1795     if (!formatEntry)
1796     {
1797         WARN("could not upload requested glyphs\n");
1798         LeaveCriticalSection(&xrender_cs);
1799         return FALSE;
1800     }
1801
1802     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1803           physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
1804
1805     elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1806     pict = get_xrender_picture( physdev, 0, (flags & ETO_CLIPPED) ? lprect : NULL );
1807
1808     /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1809        So we pass zeros to the function and move to our starting position using the first
1810        element of the elts array. */
1811
1812     desired.x = physdev->x11dev->dc_rect.left + x;
1813     desired.y = physdev->x11dev->dc_rect.top + y;
1814     offset.x = offset.y = 0;
1815     current.x = current.y = 0;
1816
1817     get_xrender_color(physdev->pict_format, physdev->x11dev->textPixel, &col);
1818     tile_pict = get_tile_pict(physdev->format, &col);
1819
1820     /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1821      */
1822     if((physdev->format == WXR_FORMAT_MONO) && (textPixel == 0))
1823         render_op = PictOpOutReverse; /* This gives us 'black' text */
1824
1825     for(idx = 0; idx < count; idx++)
1826     {
1827         elts[idx].glyphset = formatEntry->glyphset;
1828         elts[idx].chars = wstr + idx;
1829         elts[idx].nchars = 1;
1830         elts[idx].xOff = desired.x - current.x;
1831         elts[idx].yOff = desired.y - current.y;
1832
1833         current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1834         current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1835
1836         if(!lpDx)
1837         {
1838             desired.x += formatEntry->gis[wstr[idx]].xOff;
1839             desired.y += formatEntry->gis[wstr[idx]].yOff;
1840         }
1841         else
1842         {
1843             if(flags & ETO_PDY)
1844             {
1845                 offset.x += lpDx[idx * 2];
1846                 offset.y += lpDx[idx * 2 + 1];
1847             }
1848             else
1849                 offset.x += lpDx[idx];
1850             desired.x = physdev->x11dev->dc_rect.left + x + offset.x;
1851             desired.y = physdev->x11dev->dc_rect.top  + y + offset.y;
1852         }
1853     }
1854
1855     wine_tsx11_lock();
1856     /* Make sure we don't have any transforms set from a previous call */
1857     set_xrender_transformation(pict, 1, 1, 0, 0);
1858     pXRenderCompositeText16(gdi_display, render_op,
1859                             tile_pict,
1860                             pict,
1861                             formatEntry->font_format,
1862                             0, 0, 0, 0, elts, count);
1863     wine_tsx11_unlock();
1864     HeapFree(GetProcessHeap(), 0, elts);
1865
1866     LeaveCriticalSection(&xrender_cs);
1867     return TRUE;
1868 }
1869
1870 /* multiply the alpha channel of a picture */
1871 static void multiply_alpha( Picture pict, XRenderPictFormat *format, int alpha,
1872                             int x, int y, int width, int height )
1873 {
1874     XRenderPictureAttributes pa;
1875     Pixmap src_pixmap, mask_pixmap;
1876     Picture src_pict, mask_pict;
1877     XRenderColor color;
1878
1879     wine_tsx11_lock();
1880     src_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
1881     mask_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
1882     pa.repeat = RepeatNormal;
1883     src_pict = pXRenderCreatePicture( gdi_display, src_pixmap, format, CPRepeat, &pa );
1884     pa.component_alpha = True;
1885     mask_pict = pXRenderCreatePicture( gdi_display, mask_pixmap, format, CPRepeat|CPComponentAlpha, &pa );
1886     color.red = color.green = color.blue = color.alpha = 0xffff;
1887     pXRenderFillRectangle( gdi_display, PictOpSrc, src_pict, &color, 0, 0, 1, 1 );
1888     color.alpha = alpha;
1889     pXRenderFillRectangle( gdi_display, PictOpSrc, mask_pict, &color, 0, 0, 1, 1 );
1890     pXRenderComposite( gdi_display, PictOpInReverse, src_pict, mask_pict, pict,
1891                        0, 0, 0, 0, x, y, width, height );
1892     pXRenderFreePicture( gdi_display, src_pict );
1893     pXRenderFreePicture( gdi_display, mask_pict );
1894     XFreePixmap( gdi_display, src_pixmap );
1895     XFreePixmap( gdi_display, mask_pixmap );
1896     wine_tsx11_unlock();
1897 }
1898
1899 /* Helper function for (stretched) blitting using xrender */
1900 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
1901                           int x_src, int y_src, int x_dst, int y_dst,
1902                           double xscale, double yscale, int width, int height )
1903 {
1904     int x_offset, y_offset;
1905
1906     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
1907      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
1908      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
1909     wine_tsx11_lock();
1910     if(xscale != 1.0 || yscale != 1.0)
1911     {
1912         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1913          * in the wrong quadrant of the x-y plane.
1914          */
1915         x_offset = (xscale < 0) ? -width : 0;
1916         y_offset = (yscale < 0) ? -height : 0;
1917         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1918     }
1919     else
1920     {
1921         x_offset = x_src;
1922         y_offset = y_src;
1923         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1924     }
1925     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
1926                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
1927     wine_tsx11_unlock();
1928 }
1929
1930 /* Helper function for (stretched) mono->color blitting using xrender */
1931 static void xrender_mono_blit( Picture src_pict, Picture dst_pict,
1932                                enum wxr_format dst_format, XRenderColor *fg, XRenderColor *bg,
1933                                int x_src, int y_src, int x_dst, int y_dst,
1934                                double xscale, double yscale, int width, int height )
1935 {
1936     Picture tile_pict;
1937     int x_offset, y_offset;
1938     XRenderColor color;
1939
1940     /* When doing a mono->color blit, the source data is used as mask, and the source picture
1941      * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
1942      * the tile data.
1943      */
1944     EnterCriticalSection( &xrender_cs );
1945     color = *bg;
1946     color.alpha = 0xffff;  /* tile pict needs 100% alpha */
1947     tile_pict = get_tile_pict( dst_format, &color );
1948
1949     wine_tsx11_lock();
1950     pXRenderFillRectangle( gdi_display, PictOpSrc, dst_pict, fg, x_dst, y_dst, width, height );
1951
1952     if (xscale != 1.0 || yscale != 1.0)
1953     {
1954         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1955          * in the wrong quadrant of the x-y plane.
1956          */
1957         x_offset = (xscale < 0) ? -width : 0;
1958         y_offset = (yscale < 0) ? -height : 0;
1959         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1960     }
1961     else
1962     {
1963         x_offset = x_src;
1964         y_offset = y_src;
1965         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1966     }
1967     pXRenderComposite(gdi_display, PictOpOver, tile_pict, src_pict, dst_pict,
1968                       0, 0, x_offset, y_offset, x_dst, y_dst, width, height );
1969     wine_tsx11_unlock();
1970     LeaveCriticalSection( &xrender_cs );
1971
1972     /* force the alpha channel for background pixels, it has been set to 100% by the tile */
1973     if (bg->alpha != 0xffff && (dst_format == WXR_FORMAT_A8R8G8B8 || dst_format == WXR_FORMAT_B8G8R8A8))
1974         multiply_alpha( dst_pict, pict_formats[dst_format], bg->alpha, x_dst, y_dst, width, height );
1975 }
1976
1977 /* create a pixmap and render picture for an image */
1978 static DWORD create_image_pixmap( BITMAPINFO *info, const struct gdi_image_bits *bits,
1979                                   struct bitblt_coords *src, enum wxr_format format,
1980                                   Pixmap *pixmap, Picture *pict, BOOL *use_repeat )
1981 {
1982     DWORD ret;
1983     int width = src->visrect.right - src->visrect.left;
1984     int height = src->visrect.bottom - src->visrect.top;
1985     int depth = pict_formats[format]->depth;
1986     struct gdi_image_bits dst_bits;
1987     XRenderPictureAttributes pa;
1988     XImage *image;
1989
1990     wine_tsx11_lock();
1991     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1992                           info->bmiHeader.biWidth, height, 32, 0 );
1993     wine_tsx11_unlock();
1994     if (!image) return ERROR_OUTOFMEMORY;
1995
1996     ret = copy_image_bits( info, (format == WXR_FORMAT_R8G8B8), image, bits, &dst_bits, src, NULL, ~0u );
1997     if (ret) return ret;
1998
1999     image->data = dst_bits.ptr;
2000     /* hack: make sure the bits are readable if we are reading from a DIB section */
2001     /* to be removed once we get rid of DIB access protections */
2002     if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, image->height * image->bytes_per_line );
2003
2004     *use_repeat = (width == 1 && height == 1);
2005     pa.repeat = *use_repeat ? RepeatNormal : RepeatNone;
2006
2007     wine_tsx11_lock();
2008     *pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
2009     XPutImage( gdi_display, *pixmap, get_bitmap_gc( depth ), image,
2010                src->visrect.left, 0, 0, 0, width, height );
2011     *pict = pXRenderCreatePicture( gdi_display, *pixmap, pict_formats[format], CPRepeat, &pa );
2012     wine_tsx11_unlock();
2013
2014     /* make coordinates relative to the pixmap */
2015     src->x -= src->visrect.left;
2016     src->y -= src->visrect.top;
2017     OffsetRect( &src->visrect, -src->visrect.left, -src->visrect.top );
2018
2019     image->data = NULL;
2020     wine_tsx11_lock();
2021     XDestroyImage( image );
2022     wine_tsx11_unlock();
2023     if (dst_bits.free) dst_bits.free( &dst_bits );
2024     return ret;
2025 }
2026
2027 static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
2028                                   Drawable drawable, const struct bitblt_coords *src,
2029                                   const struct bitblt_coords *dst )
2030 {
2031     int width = abs( dst->width );
2032     int height = abs( dst->height );
2033     int x_src = physdev_src->x11dev->dc_rect.left + src->x;
2034     int y_src = physdev_src->x11dev->dc_rect.top + src->y;
2035     int x_dst, y_dst;
2036     Picture src_pict = 0, dst_pict, mask_pict = 0;
2037     BOOL use_repeat;
2038     double xscale, yscale;
2039
2040     use_repeat = use_source_repeat( physdev_src );
2041     if (!use_repeat)
2042     {
2043         xscale = src->width / (double)dst->width;
2044         yscale = src->height / (double)dst->height;
2045     }
2046     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2047
2048     if (drawable)  /* using an intermediate pixmap */
2049     {
2050         XRenderPictureAttributes pa;
2051
2052         x_dst = dst->x;
2053         y_dst = dst->y;
2054         pa.repeat = RepeatNone;
2055         wine_tsx11_lock();
2056         dst_pict = pXRenderCreatePicture( gdi_display, drawable, physdev_dst->pict_format, CPRepeat, &pa );
2057         wine_tsx11_unlock();
2058     }
2059     else
2060     {
2061         x_dst = physdev_dst->x11dev->dc_rect.left + dst->x;
2062         y_dst = physdev_dst->x11dev->dc_rect.top + dst->y;
2063         dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
2064     }
2065
2066     if (src->width < 0) x_src += src->width + 1;
2067     if (src->height < 0) y_src += src->height + 1;
2068     if (dst->width < 0) x_dst += dst->width + 1;
2069     if (dst->height < 0) y_dst += dst->height + 1;
2070
2071     src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2072
2073     /* mono -> color */
2074     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2075     {
2076         XRenderColor fg, bg;
2077
2078         get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->textPixel, &fg );
2079         get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->backgroundPixel, &bg );
2080         fg.alpha = bg.alpha = 0;
2081
2082         xrender_mono_blit( src_pict, dst_pict, physdev_dst->format, &fg, &bg,
2083                            x_src, y_src, x_dst, y_dst, xscale, yscale, width, height );
2084     }
2085     else /* color -> color (can be at different depths) or mono -> mono */
2086     {
2087         if (physdev_dst->x11dev->depth == 32 && physdev_src->x11dev->depth < 32)
2088             mask_pict = get_no_alpha_mask();
2089
2090         xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict,
2091                       x_src, y_src, x_dst, y_dst, xscale, yscale, width, height );
2092     }
2093
2094     if (drawable)
2095     {
2096         wine_tsx11_lock();
2097         pXRenderFreePicture( gdi_display, dst_pict );
2098         wine_tsx11_unlock();
2099     }
2100 }
2101
2102
2103 static void xrender_put_image( Pixmap src_pixmap, Picture src_pict, Picture mask_pict, HRGN clip,
2104                                XRenderPictFormat *dst_format, struct xrender_physdev *physdev,
2105                                Drawable drawable, struct bitblt_coords *src,
2106                                struct bitblt_coords *dst, BOOL use_repeat )
2107 {
2108     int x_src, y_src, x_dst, y_dst;
2109     Picture dst_pict;
2110     XRenderPictureAttributes pa;
2111     double xscale, yscale;
2112
2113     if (drawable)  /* using an intermediate pixmap */
2114     {
2115         RGNDATA *clip_data = NULL;
2116
2117         if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
2118         x_dst = dst->x;
2119         y_dst = dst->y;
2120         pa.repeat = RepeatNone;
2121         wine_tsx11_lock();
2122         dst_pict = pXRenderCreatePicture( gdi_display, drawable, dst_format, CPRepeat, &pa );
2123         if (clip_data)
2124             pXRenderSetPictureClipRectangles( gdi_display, dst_pict, 0, 0,
2125                                               (XRectangle *)clip_data->Buffer, clip_data->rdh.nCount );
2126         wine_tsx11_unlock();
2127         HeapFree( GetProcessHeap(), 0, clip_data );
2128     }
2129     else
2130     {
2131         x_dst = physdev->x11dev->dc_rect.left + dst->x;
2132         y_dst = physdev->x11dev->dc_rect.top + dst->y;
2133         dst_pict = get_xrender_picture( physdev, clip, &dst->visrect );
2134     }
2135
2136     if (!use_repeat)
2137     {
2138         xscale = src->width / (double)dst->width;
2139         yscale = src->height / (double)dst->height;
2140     }
2141     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2142
2143     x_src = src->x;
2144     y_src = src->y;
2145     if (src->width < 0) x_src += src->width + 1;
2146     if (src->height < 0) y_src += src->height + 1;
2147     if (dst->width < 0) x_dst += dst->width + 1;
2148     if (dst->height < 0) y_dst += dst->height + 1;
2149
2150     xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict, x_src, y_src, x_dst, y_dst,
2151                   xscale, yscale, abs( dst->width ), abs( dst->height ));
2152
2153     if (drawable)
2154     {
2155         wine_tsx11_lock();
2156         pXRenderFreePicture( gdi_display, dst_pict );
2157         wine_tsx11_unlock();
2158     }
2159 }
2160
2161
2162 /***********************************************************************
2163  *           xrenderdrv_StretchBlt
2164  */
2165 static BOOL xrenderdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
2166                                    PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
2167 {
2168     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2169     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2170     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2171
2172     if (src_dev->funcs != dst_dev->funcs)
2173     {
2174         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
2175         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
2176     }
2177
2178     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2179
2180     /* XRender is of no use for color -> mono */
2181     if (physdev_dst->format == WXR_FORMAT_MONO && physdev_src->format != WXR_FORMAT_MONO)
2182         goto x11drv_fallback;
2183
2184     /* if not stretching, we only need to handle format conversion */
2185     if (!stretch && physdev_dst->format == physdev_src->format) goto x11drv_fallback;
2186
2187     if (rop != SRCCOPY)
2188     {
2189         GC tmpGC;
2190         Pixmap tmp_pixmap;
2191         struct bitblt_coords tmp;
2192
2193         /* make coordinates relative to tmp pixmap */
2194         tmp = *dst;
2195         tmp.x -= tmp.visrect.left;
2196         tmp.y -= tmp.visrect.top;
2197         OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2198
2199         wine_tsx11_lock();
2200         tmpGC = XCreateGC( gdi_display, physdev_dst->x11dev->drawable, 0, NULL );
2201         XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
2202         XSetGraphicsExposures( gdi_display, tmpGC, False );
2203         tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2204                                     tmp.visrect.bottom - tmp.visrect.top, physdev_dst->x11dev->depth );
2205         wine_tsx11_unlock();
2206
2207         xrender_stretch_blit( physdev_src, physdev_dst, tmp_pixmap, src, &tmp );
2208         execute_rop( physdev_dst->x11dev, tmp_pixmap, tmpGC, &dst->visrect, rop );
2209
2210         wine_tsx11_lock();
2211         XFreePixmap( gdi_display, tmp_pixmap );
2212         XFreeGC( gdi_display, tmpGC );
2213         wine_tsx11_unlock();
2214     }
2215     else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
2216
2217     return TRUE;
2218
2219 x11drv_fallback:
2220     return X11DRV_StretchBlt( &physdev_dst->x11dev->dev, dst, &physdev_src->x11dev->dev, src, rop );
2221 }
2222
2223
2224 /***********************************************************************
2225  *           xrenderdrv_PutImage
2226  */
2227 static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
2228                                   const struct gdi_image_bits *bits, struct bitblt_coords *src,
2229                                   struct bitblt_coords *dst, DWORD rop )
2230 {
2231     struct xrender_physdev *physdev;
2232     X_PHYSBITMAP *bitmap;
2233     DWORD ret;
2234     Pixmap tmp_pixmap;
2235     GC gc;
2236     enum wxr_format src_format, dst_format;
2237     XRenderPictFormat *pict_format;
2238     Pixmap src_pixmap;
2239     Picture src_pict, mask_pict = 0;
2240     BOOL use_repeat;
2241
2242     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2243
2244     if (hbitmap)
2245     {
2246         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
2247         physdev = NULL;
2248         dst_format = get_xrender_format_from_color_shifts( bitmap->depth, &bitmap->color_shifts );
2249     }
2250     else
2251     {
2252         physdev = get_xrender_dev( dev );
2253         bitmap = NULL;
2254         dst_format = physdev->format;
2255     }
2256
2257     src_format = get_xrender_format_from_bitmapinfo( info );
2258     if (!(pict_format = pict_formats[src_format])) goto update_format;
2259
2260     /* make sure we can create an image with the same bpp */
2261     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2262         goto update_format;
2263
2264     /* mono <-> color conversions not supported */
2265     if ((src_format != dst_format) && (src_format == WXR_FORMAT_MONO || dst_format == WXR_FORMAT_MONO))
2266         goto x11drv_fallback;
2267
2268     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2269
2270     if (!has_alpha( src_format ) && has_alpha( dst_format )) mask_pict = get_no_alpha_mask();
2271
2272     ret = create_image_pixmap( info, bits, src, src_format, &src_pixmap, &src_pict, &use_repeat );
2273     if (!ret)
2274     {
2275         struct bitblt_coords tmp;
2276
2277         if (bitmap)
2278         {
2279             HRGN rgn = CreateRectRgnIndirect( &dst->visrect );
2280             if (clip) CombineRgn( rgn, rgn, clip, RGN_AND );
2281
2282             xrender_put_image( src_pixmap, src_pict, mask_pict, rgn,
2283                                pict_formats[dst_format], NULL, bitmap->pixmap, src, dst, use_repeat );
2284             DeleteObject( rgn );
2285         }
2286         else
2287         {
2288             if (rop != SRCCOPY)
2289             {
2290                 BOOL restore_region = add_extra_clipping_region( physdev->x11dev, clip );
2291
2292                 /* make coordinates relative to tmp pixmap */
2293                 tmp = *dst;
2294                 tmp.x -= tmp.visrect.left;
2295                 tmp.y -= tmp.visrect.top;
2296                 OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2297
2298                 wine_tsx11_lock();
2299                 gc = XCreateGC( gdi_display, physdev->x11dev->drawable, 0, NULL );
2300                 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
2301                 XSetGraphicsExposures( gdi_display, gc, False );
2302                 tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2303                                             tmp.visrect.bottom - tmp.visrect.top, physdev->x11dev->depth );
2304                 wine_tsx11_unlock();
2305
2306                 xrender_put_image( src_pixmap, src_pict, mask_pict, NULL, physdev->pict_format,
2307                                    NULL, tmp_pixmap, src, &tmp, use_repeat );
2308                 execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
2309
2310                 wine_tsx11_lock();
2311                 XFreePixmap( gdi_display, tmp_pixmap );
2312                 XFreeGC( gdi_display, gc );
2313                 wine_tsx11_unlock();
2314
2315                 if (restore_region) restore_clipping_region( physdev->x11dev );
2316             }
2317             else xrender_put_image( src_pixmap, src_pict, mask_pict, clip,
2318                                     physdev->pict_format, physdev, 0, src, dst, use_repeat );
2319         }
2320
2321         wine_tsx11_lock();
2322         pXRenderFreePicture( gdi_display, src_pict );
2323         XFreePixmap( gdi_display, src_pixmap );
2324         wine_tsx11_unlock();
2325     }
2326     return ret;
2327
2328 update_format:
2329     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2330     set_color_info( pict_formats[dst_format], info );
2331     return ERROR_BAD_FORMAT;
2332
2333 x11drv_fallback:
2334     if (hbitmap) return X11DRV_PutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
2335     dev = GET_NEXT_PHYSDEV( dev, pPutImage );
2336     return dev->funcs->pPutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
2337 }
2338
2339
2340 /***********************************************************************
2341  *           xrenderdrv_BlendImage
2342  */
2343 static DWORD xrenderdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits,
2344                                     struct bitblt_coords *src, struct bitblt_coords *dst,
2345                                     BLENDFUNCTION func )
2346 {
2347     struct xrender_physdev *physdev = get_xrender_dev( dev );
2348     DWORD ret;
2349     enum wxr_format format;
2350     XRenderPictFormat *pict_format;
2351     Picture dst_pict, src_pict, mask_pict;
2352     Pixmap src_pixmap;
2353     BOOL use_repeat;
2354
2355     if (!X11DRV_XRender_Installed)
2356     {
2357         dev = GET_NEXT_PHYSDEV( dev, pBlendImage );
2358         return dev->funcs->pBlendImage( dev, info, bits, src, dst, func );
2359     }
2360
2361     format = get_xrender_format_from_bitmapinfo( info );
2362     if (!(func.AlphaFormat & AC_SRC_ALPHA))
2363         format = get_format_without_alpha( format );
2364     else if (format != WXR_FORMAT_A8R8G8B8)
2365         return ERROR_INVALID_PARAMETER;
2366
2367     if (!(pict_format = pict_formats[format])) goto update_format;
2368
2369     /* make sure we can create an image with the same bpp */
2370     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
2371         goto update_format;
2372
2373     if (format == WXR_FORMAT_MONO && physdev->format != WXR_FORMAT_MONO)
2374         goto update_format;
2375
2376     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
2377
2378     ret = create_image_pixmap( info, bits, src, format, &src_pixmap, &src_pict, &use_repeat );
2379     if (!ret)
2380     {
2381         double xscale, yscale;
2382
2383         if (!use_repeat)
2384         {
2385             xscale = src->width / (double)dst->width;
2386             yscale = src->height / (double)dst->height;
2387         }
2388         else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2389
2390         dst_pict = get_xrender_picture( physdev, 0, &dst->visrect );
2391
2392         EnterCriticalSection( &xrender_cs );
2393         mask_pict = get_mask_pict( func.SourceConstantAlpha * 257 );
2394
2395         xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict, src->x, src->y,
2396                       physdev->x11dev->dc_rect.left + dst->x,
2397                       physdev->x11dev->dc_rect.top + dst->y,
2398                       xscale, yscale, dst->width, dst->height );
2399
2400         wine_tsx11_lock();
2401         pXRenderFreePicture( gdi_display, src_pict );
2402         XFreePixmap( gdi_display, src_pixmap );
2403         wine_tsx11_unlock();
2404
2405         LeaveCriticalSection( &xrender_cs );
2406     }
2407     return ret;
2408
2409 update_format:
2410     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
2411     set_color_info( physdev->pict_format, info );
2412     return ERROR_BAD_FORMAT;
2413 }
2414
2415
2416 /***********************************************************************
2417  *           xrenderdrv_AlphaBlend
2418  */
2419 static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
2420                                    PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2421 {
2422     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2423     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2424     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2425     XRenderPictureAttributes pa;
2426     Pixmap tmp_pixmap = 0;
2427     double xscale, yscale;
2428     BOOL use_repeat;
2429
2430     if (!X11DRV_XRender_Installed || src_dev->funcs != dst_dev->funcs)
2431     {
2432         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pAlphaBlend );
2433         return dst_dev->funcs->pAlphaBlend( dst_dev, dst, src_dev, src, blendfn );
2434     }
2435
2436     if ((blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->format != WXR_FORMAT_A8R8G8B8)
2437     {
2438         SetLastError( ERROR_INVALID_PARAMETER );
2439         return FALSE;
2440     }
2441
2442     dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
2443
2444     use_repeat = use_source_repeat( physdev_src );
2445     if (!use_repeat)
2446     {
2447         xscale = src->width / (double)dst->width;
2448         yscale = src->height / (double)dst->height;
2449     }
2450     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2451
2452     src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2453
2454     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2455     {
2456         /* mono -> color blending needs an intermediate color pixmap */
2457         XRenderColor fg, bg;
2458         int width = src->visrect.right - src->visrect.left;
2459         int height = src->visrect.bottom - src->visrect.top;
2460
2461         /* blending doesn't use the destination DC colors */
2462         fg.red = fg.green = fg.blue = 0;
2463         bg.red = bg.green = bg.blue = 0xffff;
2464         fg.alpha = bg.alpha = 0xffff;
2465
2466         wine_tsx11_lock();
2467         tmp_pixmap = XCreatePixmap( gdi_display, root_window, width, height,
2468                                     physdev_dst->pict_format->depth );
2469         pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2470         tmp_pict = pXRenderCreatePicture( gdi_display, tmp_pixmap, physdev_dst->pict_format,
2471                                           CPRepeat, &pa );
2472         wine_tsx11_unlock();
2473
2474         xrender_mono_blit( src_pict, tmp_pict, physdev_dst->format, &fg, &bg,
2475                            src->visrect.left, src->visrect.top, 0, 0, 1, 1, width, height );
2476     }
2477     else if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->pict_format)
2478     {
2479         /* we need a source picture with no alpha */
2480         enum wxr_format format = get_format_without_alpha( physdev_src->format );
2481         if (format != physdev_src->format)
2482         {
2483             wine_tsx11_lock();
2484             pa.subwindow_mode = IncludeInferiors;
2485             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2486             tmp_pict = pXRenderCreatePicture( gdi_display, physdev_src->x11dev->drawable,
2487                                               pict_formats[format], CPSubwindowMode|CPRepeat, &pa );
2488             wine_tsx11_unlock();
2489         }
2490     }
2491
2492     if (tmp_pict) src_pict = tmp_pict;
2493
2494     EnterCriticalSection( &xrender_cs );
2495     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2496
2497     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2498                   physdev_src->x11dev->dc_rect.left + src->x,
2499                   physdev_src->x11dev->dc_rect.top + src->y,
2500                   physdev_dst->x11dev->dc_rect.left + dst->x,
2501                   physdev_dst->x11dev->dc_rect.top + dst->y,
2502                   xscale, yscale, dst->width, dst->height );
2503
2504     wine_tsx11_lock();
2505     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2506     if (tmp_pixmap) XFreePixmap( gdi_display, tmp_pixmap );
2507     wine_tsx11_unlock();
2508
2509     LeaveCriticalSection( &xrender_cs );
2510     return TRUE;
2511 }
2512
2513 /***********************************************************************
2514  *           xrenderdrv_GradientFill
2515  */
2516 static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
2517                                      void * grad_array, ULONG ngrad, ULONG mode )
2518 {
2519 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
2520     static const XFixed stops[2] = { 0, 1 << 16 };
2521     struct xrender_physdev *physdev = get_xrender_dev( dev );
2522     XLinearGradient gradient;
2523     XRenderColor colors[2];
2524     Picture src_pict, dst_pict;
2525     unsigned int i;
2526     const GRADIENT_RECT *rect = grad_array;
2527     POINT pt[2];
2528
2529     if (!X11DRV_XRender_Installed) goto fallback;
2530     if (!pXRenderCreateLinearGradient) goto fallback;
2531
2532     /* <= 16-bpp uses dithering */
2533     if (!physdev->pict_format || physdev->pict_format->depth <= 16) goto fallback;
2534
2535     switch (mode)
2536     {
2537     case GRADIENT_FILL_RECT_H:
2538     case GRADIENT_FILL_RECT_V:
2539         for (i = 0; i < ngrad; i++, rect++)
2540         {
2541             const TRIVERTEX *v1 = vert_array + rect->UpperLeft;
2542             const TRIVERTEX *v2 = vert_array + rect->LowerRight;
2543
2544             colors[0].red   = v1->Red * 257 / 256;
2545             colors[0].green = v1->Green * 257 / 256;
2546             colors[0].blue  = v1->Blue * 257 / 256;
2547             colors[1].red   = v2->Red * 257 / 256;
2548             colors[1].green = v2->Green * 257 / 256;
2549             colors[1].blue  = v2->Blue * 257 / 256;
2550             /* always ignore alpha since otherwise xrender will want to pre-multiply the colors */
2551             colors[0].alpha = colors[1].alpha = 65535;
2552
2553             pt[0].x = v1->x;
2554             pt[0].y = v1->y;
2555             pt[1].x = v2->x;
2556             pt[1].y = v2->y;
2557             LPtoDP( dev->hdc, pt, 2 );
2558             if (mode == GRADIENT_FILL_RECT_H)
2559             {
2560                 gradient.p1.y = gradient.p2.y = 0;
2561                 if (pt[1].x > pt[0].x)
2562                 {
2563                     gradient.p1.x = 0;
2564                     gradient.p2.x = (pt[1].x - pt[0].x) << 16;
2565                 }
2566                 else
2567                 {
2568                     gradient.p1.x = (pt[0].x - pt[1].x) << 16;
2569                     gradient.p2.x = 0;
2570                 }
2571             }
2572             else
2573             {
2574                 gradient.p1.x = gradient.p2.x = 0;
2575                 if (pt[1].y > pt[0].y)
2576                 {
2577                     gradient.p1.y = 0;
2578                     gradient.p2.y = (pt[1].y - pt[0].y) << 16;
2579                 }
2580                 else
2581                 {
2582                     gradient.p1.y = (pt[0].y - pt[1].y) << 16;
2583                     gradient.p2.y = 0;
2584                 }
2585             }
2586
2587             TRACE( "%u gradient %d,%d - %d,%d colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n",
2588                    mode, pt[0].x, pt[0].y, pt[1].x, pt[1].y,
2589                    colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha,
2590                    colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha );
2591
2592             dst_pict = get_xrender_picture( physdev, 0, NULL );
2593
2594             wine_tsx11_lock();
2595             src_pict = pXRenderCreateLinearGradient( gdi_display, &gradient, stops, colors, 2 );
2596             xrender_blit( PictOpSrc, src_pict, 0, dst_pict, 0, 0,
2597                           physdev->x11dev->dc_rect.left + min( pt[0].x, pt[1].x ),
2598                           physdev->x11dev->dc_rect.top + min( pt[0].y, pt[1].y ),
2599                           1, 1, abs(pt[1].x - pt[0].x), abs(pt[1].y - pt[0].y) );
2600             pXRenderFreePicture( gdi_display, src_pict );
2601             wine_tsx11_unlock();
2602         }
2603         return TRUE;
2604     }
2605
2606 fallback:
2607 #endif
2608     dev = GET_NEXT_PHYSDEV( dev, pGradientFill );
2609     return dev->funcs->pGradientFill( dev, vert_array, nvert, grad_array, ngrad, mode );
2610 }
2611
2612 /***********************************************************************
2613  *           xrenderdrv_SelectBrush
2614  */
2615 static HBRUSH xrenderdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern )
2616 {
2617     struct xrender_physdev *physdev = get_xrender_dev( dev );
2618     X_PHYSBITMAP *physbitmap;
2619     enum wxr_format format;
2620     BOOL delete_bitmap = FALSE;
2621     BITMAP bm;
2622     HBITMAP bitmap;
2623     Pixmap pixmap;
2624     Picture src_pict, dst_pict;
2625     XRenderPictureAttributes pa;
2626
2627     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2628     if (!pattern) goto x11drv_fallback;
2629     if (physdev->format == WXR_FORMAT_MONO) goto x11drv_fallback;
2630
2631     bitmap = pattern->bitmap;
2632     if (!bitmap || !(physbitmap = X11DRV_get_phys_bitmap( bitmap )))
2633     {
2634         if (!(bitmap = create_brush_bitmap( physdev->x11dev, pattern ))) return 0;
2635         physbitmap = X11DRV_get_phys_bitmap( bitmap );
2636         delete_bitmap = TRUE;
2637     }
2638
2639     format = get_xrender_format_from_color_shifts( physbitmap->depth, &physbitmap->color_shifts );
2640     if (format == WXR_FORMAT_MONO || !pict_formats[format]) goto x11drv_fallback;
2641
2642     GetObjectW( bitmap, sizeof(bm), &bm );
2643
2644     X11DRV_DIB_Lock( physbitmap, DIB_Status_GdiMod );
2645
2646     wine_tsx11_lock();
2647     pixmap = XCreatePixmap( gdi_display, root_window, bm.bmWidth, bm.bmHeight,
2648                             physdev->pict_format->depth );
2649
2650     pa.repeat = RepeatNone;
2651     src_pict = pXRenderCreatePicture(gdi_display, physbitmap->pixmap, pict_formats[format], CPRepeat, &pa);
2652     dst_pict = pXRenderCreatePicture(gdi_display, pixmap, physdev->pict_format, CPRepeat, &pa);
2653
2654     xrender_blit( PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, bm.bmWidth, bm.bmHeight );
2655     pXRenderFreePicture( gdi_display, src_pict );
2656     pXRenderFreePicture( gdi_display, dst_pict );
2657
2658     if (physdev->x11dev->brush.pixmap) XFreePixmap( gdi_display, physdev->x11dev->brush.pixmap );
2659     physdev->x11dev->brush.pixmap = pixmap;
2660     physdev->x11dev->brush.fillStyle = FillTiled;
2661     physdev->x11dev->brush.pixel = 0;  /* ignored */
2662     physdev->x11dev->brush.style = BS_PATTERN;
2663     wine_tsx11_unlock();
2664
2665     X11DRV_DIB_Unlock( physbitmap, TRUE );
2666     if (delete_bitmap) DeleteObject( bitmap );
2667     return hbrush;
2668
2669 x11drv_fallback:
2670     if (delete_bitmap) DeleteObject( bitmap );
2671     dev = GET_NEXT_PHYSDEV( dev, pSelectBrush );
2672     return dev->funcs->pSelectBrush( dev, hbrush, pattern );
2673 }
2674
2675
2676 static const struct gdi_dc_funcs xrender_funcs =
2677 {
2678     NULL,                               /* pAbortDoc */
2679     NULL,                               /* pAbortPath */
2680     xrenderdrv_AlphaBlend,              /* pAlphaBlend */
2681     NULL,                               /* pAngleArc */
2682     NULL,                               /* pArc */
2683     NULL,                               /* pArcTo */
2684     NULL,                               /* pBeginPath */
2685     xrenderdrv_BlendImage,              /* pBlendImage */
2686     NULL,                               /* pChoosePixelFormat */
2687     NULL,                               /* pChord */
2688     NULL,                               /* pCloseFigure */
2689     xrenderdrv_CopyBitmap,              /* pCopyBitmap */
2690     xrenderdrv_CreateBitmap,            /* pCreateBitmap */
2691     xrenderdrv_CreateCompatibleDC,      /* pCreateCompatibleDC */
2692     xrenderdrv_CreateDC,                /* pCreateDC */
2693     NULL,                               /* pCreateDIBSection */
2694     xrenderdrv_DeleteBitmap,            /* pDeleteBitmap */
2695     xrenderdrv_DeleteDC,                /* pDeleteDC */
2696     NULL,                               /* pDeleteObject */
2697     NULL,                               /* pDescribePixelFormat */
2698     NULL,                               /* pDeviceCapabilities */
2699     NULL,                               /* pEllipse */
2700     NULL,                               /* pEndDoc */
2701     NULL,                               /* pEndPage */
2702     NULL,                               /* pEndPath */
2703     NULL,                               /* pEnumFonts */
2704     NULL,                               /* pEnumICMProfiles */
2705     NULL,                               /* pExcludeClipRect */
2706     NULL,                               /* pExtDeviceMode */
2707     xrenderdrv_ExtEscape,               /* pExtEscape */
2708     NULL,                               /* pExtFloodFill */
2709     NULL,                               /* pExtSelectClipRgn */
2710     xrenderdrv_ExtTextOut,              /* pExtTextOut */
2711     NULL,                               /* pFillPath */
2712     NULL,                               /* pFillRgn */
2713     NULL,                               /* pFlattenPath */
2714     NULL,                               /* pFontIsLinked */
2715     NULL,                               /* pFrameRgn */
2716     NULL,                               /* pGdiComment */
2717     NULL,                               /* pGdiRealizationInfo */
2718     NULL,                               /* pGetCharABCWidths */
2719     NULL,                               /* pGetCharABCWidthsI */
2720     NULL,                               /* pGetCharWidth */
2721     NULL,                               /* pGetDeviceCaps */
2722     NULL,                               /* pGetDeviceGammaRamp */
2723     NULL,                               /* pGetFontData */
2724     NULL,                               /* pGetFontUnicodeRanges */
2725     NULL,                               /* pGetGlyphIndices */
2726     NULL,                               /* pGetGlyphOutline */
2727     NULL,                               /* pGetICMProfile */
2728     xrenderdrv_GetImage,                /* pGetImage */
2729     NULL,                               /* pGetKerningPairs */
2730     NULL,                               /* pGetNearestColor */
2731     NULL,                               /* pGetOutlineTextMetrics */
2732     NULL,                               /* pGetPixel */
2733     NULL,                               /* pGetPixelFormat */
2734     NULL,                               /* pGetSystemPaletteEntries */
2735     NULL,                               /* pGetTextCharsetInfo */
2736     NULL,                               /* pGetTextExtentExPoint */
2737     NULL,                               /* pGetTextExtentExPointI */
2738     NULL,                               /* pGetTextFace */
2739     NULL,                               /* pGetTextMetrics */
2740     xrenderdrv_GradientFill,            /* pGradientFill */
2741     NULL,                               /* pIntersectClipRect */
2742     NULL,                               /* pInvertRgn */
2743     NULL,                               /* pLineTo */
2744     NULL,                               /* pModifyWorldTransform */
2745     NULL,                               /* pMoveTo */
2746     NULL,                               /* pOffsetClipRgn */
2747     NULL,                               /* pOffsetViewportOrg */
2748     NULL,                               /* pOffsetWindowOrg */
2749     NULL,                               /* pPaintRgn */
2750     NULL,                               /* pPatBlt */
2751     NULL,                               /* pPie */
2752     NULL,                               /* pPolyBezier */
2753     NULL,                               /* pPolyBezierTo */
2754     NULL,                               /* pPolyDraw */
2755     NULL,                               /* pPolyPolygon */
2756     NULL,                               /* pPolyPolyline */
2757     NULL,                               /* pPolygon */
2758     NULL,                               /* pPolyline */
2759     NULL,                               /* pPolylineTo */
2760     xrenderdrv_PutImage,                /* pPutImage */
2761     NULL,                               /* pRealizeDefaultPalette */
2762     NULL,                               /* pRealizePalette */
2763     NULL,                               /* pRectangle */
2764     NULL,                               /* pResetDC */
2765     NULL,                               /* pRestoreDC */
2766     NULL,                               /* pRoundRect */
2767     NULL,                               /* pSaveDC */
2768     NULL,                               /* pScaleViewportExt */
2769     NULL,                               /* pScaleWindowExt */
2770     xrenderdrv_SelectBitmap,            /* pSelectBitmap */
2771     xrenderdrv_SelectBrush,             /* pSelectBrush */
2772     NULL,                               /* pSelectClipPath */
2773     xrenderdrv_SelectFont,              /* pSelectFont */
2774     NULL,                               /* pSelectPalette */
2775     NULL,                               /* pSelectPen */
2776     NULL,                               /* pSetArcDirection */
2777     NULL,                               /* pSetBkColor */
2778     NULL,                               /* pSetBkMode */
2779     NULL,                               /* pSetDCBrushColor */
2780     NULL,                               /* pSetDCPenColor */
2781     NULL,                               /* pSetDIBitsToDevice */
2782     xrenderdrv_SetDeviceClipping,       /* pSetDeviceClipping */
2783     NULL,                               /* pSetDeviceGammaRamp */
2784     NULL,                               /* pSetLayout */
2785     NULL,                               /* pSetMapMode */
2786     NULL,                               /* pSetMapperFlags */
2787     NULL,                               /* pSetPixel */
2788     NULL,                               /* pSetPixelFormat */
2789     NULL,                               /* pSetPolyFillMode */
2790     NULL,                               /* pSetROP2 */
2791     NULL,                               /* pSetRelAbs */
2792     NULL,                               /* pSetStretchBltMode */
2793     NULL,                               /* pSetTextAlign */
2794     NULL,                               /* pSetTextCharacterExtra */
2795     NULL,                               /* pSetTextColor */
2796     NULL,                               /* pSetTextJustification */
2797     NULL,                               /* pSetViewportExt */
2798     NULL,                               /* pSetViewportOrg */
2799     NULL,                               /* pSetWindowExt */
2800     NULL,                               /* pSetWindowOrg */
2801     NULL,                               /* pSetWorldTransform */
2802     NULL,                               /* pStartDoc */
2803     NULL,                               /* pStartPage */
2804     xrenderdrv_StretchBlt,              /* pStretchBlt */
2805     NULL,                               /* pStretchDIBits */
2806     NULL,                               /* pStrokeAndFillPath */
2807     NULL,                               /* pStrokePath */
2808     NULL,                               /* pSwapBuffers */
2809     NULL,                               /* pUnrealizePalette */
2810     NULL,                               /* pWidenPath */
2811     /* OpenGL not supported */
2812 };
2813
2814 #else /* SONAME_LIBXRENDER */
2815
2816 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
2817 {
2818     TRACE("XRender support not compiled in.\n");
2819     return NULL;
2820 }
2821
2822 void X11DRV_XRender_Finalize(void)
2823 {
2824 }
2825
2826 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2827 {
2828     return FALSE;
2829 }
2830
2831 #endif /* SONAME_LIBXRENDER */