user32: Use the stored color and mask bitmaps instead of the raw bits in GetIconInfo.
[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  *
7  * Some parts also:
8  * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "x11drv.h"
35 #include "winternl.h"
36 #include "wine/library.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
39
40 int using_client_side_fonts = FALSE;
41
42 WINE_DEFAULT_DEBUG_CHANNEL(xrender);
43
44 #ifdef SONAME_LIBXRENDER
45
46 static BOOL X11DRV_XRender_Installed = FALSE;
47
48 #include <X11/Xlib.h>
49 #include <X11/extensions/Xrender.h>
50
51 #ifndef RepeatNone  /* added in 0.10 */
52 #define RepeatNone    0
53 #define RepeatNormal  1
54 #define RepeatPad     2
55 #define RepeatReflect 3
56 #endif
57
58 typedef enum wine_xrformat
59 {
60   WXR_FORMAT_MONO,
61   WXR_FORMAT_GRAY,
62   WXR_FORMAT_X1R5G5B5,
63   WXR_FORMAT_X1B5G5R5,
64   WXR_FORMAT_R5G6B5,
65   WXR_FORMAT_B5G6R5,
66   WXR_FORMAT_R8G8B8,
67   WXR_FORMAT_B8G8R8,
68   WXR_FORMAT_A8R8G8B8,
69   WXR_FORMAT_B8G8R8A8,
70   WXR_FORMAT_X8R8G8B8,
71   WXR_FORMAT_B8G8R8X8,
72   WXR_NB_FORMATS
73 } WXRFormat;
74
75 typedef struct wine_xrender_format_template
76 {
77     WXRFormat wxr_format;
78     unsigned int depth;
79     unsigned int alpha;
80     unsigned int alphaMask;
81     unsigned int red;
82     unsigned int redMask;
83     unsigned int green;
84     unsigned int greenMask;
85     unsigned int blue;
86     unsigned int blueMask;
87 } WineXRenderFormatTemplate;
88
89 static const WineXRenderFormatTemplate wxr_formats_template[WXR_NB_FORMATS] =
90 {
91     /* Format               depth   alpha   mask    red     mask    green   mask    blue    mask*/
92     {WXR_FORMAT_MONO,       1,      0,      0x01,   0,      0,      0,      0,      0,      0       },
93     {WXR_FORMAT_GRAY,       8,      0,      0xff,   0,      0,      0,      0,      0,      0       },
94     {WXR_FORMAT_X1R5G5B5,   16,     0,      0,      10,     0x1f,   5,      0x1f,   0,      0x1f    },
95     {WXR_FORMAT_X1B5G5R5,   16,     0,      0,      0,      0x1f,   5,      0x1f,   10,     0x1f    },
96     {WXR_FORMAT_R5G6B5,     16,     0,      0,      11,     0x1f,   5,      0x3f,   0,      0x1f    },
97     {WXR_FORMAT_B5G6R5,     16,     0,      0,      0,      0x1f,   5,      0x3f,   11,     0x1f    },
98     {WXR_FORMAT_R8G8B8,     24,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
99     {WXR_FORMAT_B8G8R8,     24,     0,      0,      0,      0xff,   8,      0xff,   16,     0xff    },
100     {WXR_FORMAT_A8R8G8B8,   32,     24,     0xff,   16,     0xff,   8,      0xff,   0,      0xff    },
101     {WXR_FORMAT_B8G8R8A8,   32,     0,      0xff,   8,      0xff,   16,     0xff,   24,     0xff    },
102     {WXR_FORMAT_X8R8G8B8,   32,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
103     {WXR_FORMAT_B8G8R8X8,   32,     0,      0,      8,      0xff,   16,     0xff,   24,     0xff    },
104 };
105
106 typedef struct wine_xrender_format
107 {
108     WXRFormat               format;
109     XRenderPictFormat       *pict_format;
110 } WineXRenderFormat;
111
112 static WineXRenderFormat wxr_formats[WXR_NB_FORMATS];
113 static int WineXRenderFormatsListSize = 0;
114 static WineXRenderFormat *default_format = NULL;
115
116 typedef struct
117 {
118     LOGFONTW lf;
119     XFORM    xform;
120     SIZE     devsize;  /* size in device coords */
121     DWORD    hash;
122 } LFANDSIZE;
123
124 #define INITIAL_REALIZED_BUF_SIZE 128
125
126 typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
127
128 typedef struct
129 {
130     GlyphSet glyphset;
131     const WineXRenderFormat *font_format;
132     int nrealized;
133     BOOL *realized;
134     void **bitmaps;
135     XGlyphInfo *gis;
136 } gsCacheEntryFormat;
137
138 typedef struct
139 {
140     LFANDSIZE lfsz;
141     AA_Type aa_default;
142     gsCacheEntryFormat * format[AA_MAXVALUE];
143     INT count;
144     INT next;
145 } gsCacheEntry;
146
147 struct xrender_info
148 {
149     int                cache_index;
150     Picture            pict;
151     Picture            pict_src;
152     const WineXRenderFormat *format;
153 };
154
155 static gsCacheEntry *glyphsetCache = NULL;
156 static DWORD glyphsetCacheSize = 0;
157 static INT lastfree = -1;
158 static INT mru = -1;
159
160 #define INIT_CACHE_SIZE 10
161
162 static int antialias = 1;
163
164 static void *xrender_handle;
165
166 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
167 MAKE_FUNCPTR(XRenderAddGlyphs)
168 MAKE_FUNCPTR(XRenderComposite)
169 MAKE_FUNCPTR(XRenderCompositeString8)
170 MAKE_FUNCPTR(XRenderCompositeString16)
171 MAKE_FUNCPTR(XRenderCompositeString32)
172 MAKE_FUNCPTR(XRenderCompositeText16)
173 MAKE_FUNCPTR(XRenderCreateGlyphSet)
174 MAKE_FUNCPTR(XRenderCreatePicture)
175 MAKE_FUNCPTR(XRenderFillRectangle)
176 MAKE_FUNCPTR(XRenderFindFormat)
177 MAKE_FUNCPTR(XRenderFindVisualFormat)
178 MAKE_FUNCPTR(XRenderFreeGlyphSet)
179 MAKE_FUNCPTR(XRenderFreePicture)
180 MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
181 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
182 MAKE_FUNCPTR(XRenderSetPictureTransform)
183 #endif
184 MAKE_FUNCPTR(XRenderQueryExtension)
185
186 #ifdef SONAME_LIBFONTCONFIG
187 #include <fontconfig/fontconfig.h>
188 MAKE_FUNCPTR(FcConfigSubstitute)
189 MAKE_FUNCPTR(FcDefaultSubstitute)
190 MAKE_FUNCPTR(FcFontMatch)
191 MAKE_FUNCPTR(FcInit)
192 MAKE_FUNCPTR(FcPatternCreate)
193 MAKE_FUNCPTR(FcPatternDestroy)
194 MAKE_FUNCPTR(FcPatternAddInteger)
195 MAKE_FUNCPTR(FcPatternAddString)
196 MAKE_FUNCPTR(FcPatternGetInteger)
197 MAKE_FUNCPTR(FcPatternGetString)
198 static void *fontconfig_handle;
199 static BOOL fontconfig_installed;
200 #endif
201
202 #undef MAKE_FUNCPTR
203
204 static CRITICAL_SECTION xrender_cs;
205 static CRITICAL_SECTION_DEBUG critsect_debug =
206 {
207     0, 0, &xrender_cs,
208     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
209       0, 0, { (DWORD_PTR)(__FILE__ ": xrender_cs") }
210 };
211 static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
212
213 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
214           ( ( (ULONG)_x4 << 24 ) |     \
215             ( (ULONG)_x3 << 16 ) |     \
216             ( (ULONG)_x2 <<  8 ) |     \
217               (ULONG)_x1         )
218
219 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
220
221 #define GASP_GRIDFIT 0x01
222 #define GASP_DOGRAY  0x02
223
224 #ifdef WORDS_BIGENDIAN
225 #define get_be_word(x) (x)
226 #define NATIVE_BYTE_ORDER MSBFirst
227 #else
228 #define get_be_word(x) RtlUshortByteSwap(x)
229 #define NATIVE_BYTE_ORDER LSBFirst
230 #endif
231
232 static WXRFormat get_format_without_alpha( WXRFormat format )
233 {
234     switch (format)
235     {
236     case WXR_FORMAT_A8R8G8B8: return WXR_FORMAT_X8R8G8B8;
237     case WXR_FORMAT_B8G8R8A8: return WXR_FORMAT_B8G8R8X8;
238     default: return format;
239     }
240 }
241
242 static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
243 {
244     templ->id = 0;
245     templ->type = PictTypeDirect;
246     templ->depth = fmt->depth;
247     templ->direct.alpha = fmt->alpha;
248     templ->direct.alphaMask = fmt->alphaMask;
249     templ->direct.red = fmt->red;
250     templ->direct.redMask = fmt->redMask;
251     templ->direct.green = fmt->green;
252     templ->direct.greenMask = fmt->greenMask;
253     templ->direct.blue = fmt->blue;
254     templ->direct.blueMask = fmt->blueMask;
255     templ->colormap = 0;
256
257     *mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
258
259     return TRUE;
260 }
261
262 static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
263 {
264     if(fmt->depth != screen_depth)
265         return FALSE;
266     if( (fmt->redMask << fmt->red) != visual->red_mask)
267         return FALSE;
268     if( (fmt->greenMask << fmt->green) != visual->green_mask)
269         return FALSE;
270     if( (fmt->blueMask << fmt->blue) != visual->blue_mask)
271         return FALSE;
272
273     /* We never select a default ARGB visual */
274     if(fmt->alphaMask)
275         return FALSE;
276
277     return TRUE;
278 }
279
280 static int load_xrender_formats(void)
281 {
282     unsigned int i;
283     for(i = 0; i < (sizeof(wxr_formats_template) / sizeof(wxr_formats_template[0])); i++)
284     {
285         XRenderPictFormat templ, *pict_format;
286
287         if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
288         {
289             wine_tsx11_lock();
290             pict_format = pXRenderFindVisualFormat(gdi_display, visual);
291             if(!pict_format)
292             {
293                 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
294                 if (visual->class == DirectColor)
295                 {
296                     XVisualInfo info;
297                     if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
298                                           screen_depth, TrueColor, &info ))
299                     {
300                         pict_format = pXRenderFindVisualFormat(gdi_display, info.visual);
301                         if (pict_format) visual = info.visual;
302                     }
303                 }
304             }
305             wine_tsx11_unlock();
306
307             if(pict_format)
308             {
309                 wxr_formats[WineXRenderFormatsListSize].format = wxr_formats_template[i].wxr_format;
310                 wxr_formats[WineXRenderFormatsListSize].pict_format = pict_format;
311                 default_format = &wxr_formats[WineXRenderFormatsListSize];
312                 WineXRenderFormatsListSize++;
313                 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_format->id, wxr_formats_template[i].wxr_format);
314             }
315         }
316         else
317         {
318             unsigned long mask = 0;
319             get_xrender_template(&wxr_formats_template[i], &templ, &mask);
320
321             wine_tsx11_lock();
322             pict_format = pXRenderFindFormat(gdi_display, mask, &templ, 0);
323             wine_tsx11_unlock();
324
325             if(pict_format)
326             {
327                 wxr_formats[WineXRenderFormatsListSize].format = wxr_formats_template[i].wxr_format;
328                 wxr_formats[WineXRenderFormatsListSize].pict_format = pict_format;
329                 WineXRenderFormatsListSize++;
330                 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_format->id, wxr_formats_template[i].wxr_format);
331             }
332         }
333     }
334     return WineXRenderFormatsListSize;
335 }
336
337 /***********************************************************************
338  *   X11DRV_XRender_Init
339  *
340  * Let's see if our XServer has the extension available
341  *
342  */
343 void X11DRV_XRender_Init(void)
344 {
345     int event_base, i;
346
347     if (client_side_with_render &&
348         wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
349         wine_dlopen(SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0) && 
350         (xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0)))
351     {
352
353 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
354 LOAD_FUNCPTR(XRenderAddGlyphs)
355 LOAD_FUNCPTR(XRenderComposite)
356 LOAD_FUNCPTR(XRenderCompositeString8)
357 LOAD_FUNCPTR(XRenderCompositeString16)
358 LOAD_FUNCPTR(XRenderCompositeString32)
359 LOAD_FUNCPTR(XRenderCompositeText16)
360 LOAD_FUNCPTR(XRenderCreateGlyphSet)
361 LOAD_FUNCPTR(XRenderCreatePicture)
362 LOAD_FUNCPTR(XRenderFillRectangle)
363 LOAD_FUNCPTR(XRenderFindFormat)
364 LOAD_FUNCPTR(XRenderFindVisualFormat)
365 LOAD_FUNCPTR(XRenderFreeGlyphSet)
366 LOAD_FUNCPTR(XRenderFreePicture)
367 LOAD_FUNCPTR(XRenderSetPictureClipRectangles)
368 LOAD_FUNCPTR(XRenderQueryExtension)
369 #undef LOAD_FUNCPTR
370 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
371 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0);
372 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform)
373 #undef LOAD_OPTIONAL_FUNCPTR
374 #endif
375
376         wine_tsx11_lock();
377         X11DRV_XRender_Installed = pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base);
378         wine_tsx11_unlock();
379         if(X11DRV_XRender_Installed) {
380             TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
381             if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
382             {
383                 wine_tsx11_unlock();
384                 WINE_MESSAGE(
385                     "Wine has detected that you probably have a buggy version\n"
386                     "of libXrender.so .  Because of this client side font rendering\n"
387                     "will be disabled.  Please upgrade this library.\n");
388                 X11DRV_XRender_Installed = FALSE;
389                 return;
390             }
391
392             if (!visual->red_mask || !visual->green_mask || !visual->blue_mask) {
393                 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
394                 X11DRV_XRender_Installed = FALSE;
395             }
396         }
397     }
398
399 #ifdef SONAME_LIBFONTCONFIG
400     if ((fontconfig_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0)))
401     {
402 #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;}
403         LOAD_FUNCPTR(FcConfigSubstitute);
404         LOAD_FUNCPTR(FcDefaultSubstitute);
405         LOAD_FUNCPTR(FcFontMatch);
406         LOAD_FUNCPTR(FcInit);
407         LOAD_FUNCPTR(FcPatternCreate);
408         LOAD_FUNCPTR(FcPatternDestroy);
409         LOAD_FUNCPTR(FcPatternAddInteger);
410         LOAD_FUNCPTR(FcPatternAddString);
411         LOAD_FUNCPTR(FcPatternGetInteger);
412         LOAD_FUNCPTR(FcPatternGetString);
413 #undef LOAD_FUNCPTR
414         fontconfig_installed = pFcInit();
415     }
416     else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG "\n" );
417 #endif
418
419 sym_not_found:
420     if(X11DRV_XRender_Installed || client_side_with_core)
421     {
422         glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
423                                   sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
424
425         glyphsetCacheSize = INIT_CACHE_SIZE;
426         lastfree = 0;
427         for(i = 0; i < INIT_CACHE_SIZE; i++) {
428           glyphsetCache[i].next = i + 1;
429           glyphsetCache[i].count = -1;
430         }
431         glyphsetCache[i-1].next = -1;
432         using_client_side_fonts = 1;
433
434         if(!X11DRV_XRender_Installed) {
435             TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
436             if(screen_depth <= 8 || !client_side_antialias_with_core)
437                 antialias = 0;
438         } else {
439             if(screen_depth <= 8 || !client_side_antialias_with_render)
440                 antialias = 0;
441         }
442     }
443     else TRACE("Using X11 core fonts\n");
444 }
445
446 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
447 static void get_xrender_color(const WineXRenderFormat *wxr_format, int src_color, XRenderColor *dst_color)
448 {
449     XRenderPictFormat *pf = wxr_format->pict_format;
450
451     if(pf->direct.redMask)
452         dst_color->red = ((src_color >> pf->direct.red) & pf->direct.redMask) * 65535/pf->direct.redMask;
453     else
454        dst_color->red = 0;
455
456     if(pf->direct.greenMask)
457         dst_color->green = ((src_color >> pf->direct.green) & pf->direct.greenMask) * 65535/pf->direct.greenMask;
458     else
459         dst_color->green = 0;
460
461     if(pf->direct.blueMask)
462         dst_color->blue = ((src_color >> pf->direct.blue) & pf->direct.blueMask) * 65535/pf->direct.blueMask;
463     else
464         dst_color->blue = 0;
465
466     dst_color->alpha = 0xffff;
467 }
468
469 static const WineXRenderFormat *get_xrender_format(WXRFormat format)
470 {
471     int i;
472     for(i=0; i<WineXRenderFormatsListSize; i++)
473     {
474         if(wxr_formats[i].format == format)
475         {
476             TRACE("Returning wxr_format=%#x\n", format);
477             return &wxr_formats[i];
478         }
479     }
480     return NULL;
481 }
482
483 static const WineXRenderFormat *get_xrender_format_from_color_shifts(int depth, ColorShifts *shifts)
484 {
485     int redMask, greenMask, blueMask;
486     unsigned int i;
487
488     if(depth == 1)
489         return get_xrender_format(WXR_FORMAT_MONO);
490
491     /* physDevs of a depth <=8, don't have color_shifts set and XRender can't handle those except for 1-bit */
492     if(!shifts)
493         return default_format;
494
495     redMask   = shifts->physicalRed.max << shifts->physicalRed.shift;
496     greenMask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
497     blueMask  = shifts->physicalBlue.max << shifts->physicalBlue.shift;
498
499     /* Try to locate a format which matches the specification of the dibsection. */
500     for(i = 0; i < (sizeof(wxr_formats_template) / sizeof(wxr_formats_template[0])); i++)
501     {
502         if( depth     == wxr_formats_template[i].depth &&
503             redMask   == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
504             greenMask == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
505             blueMask  == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue) )
506
507         {
508             /* When we reach this stage the format was found in our template table but this doesn't mean that
509             * the Xserver also supports this format (e.g. its depth might be too low). The call below verifies that.
510             */
511             return get_xrender_format(wxr_formats_template[i].wxr_format);
512         }
513     }
514
515     /* This should not happen because when we reach 'shifts' must have been set and we only allows shifts which are backed by X */
516     ERR("No XRender format found!\n");
517     return NULL;
518 }
519
520 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
521 static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
522 {
523 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
524     XTransform xform = {{
525         { XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(xoffset) },
526         { XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(yoffset) },
527         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
528     }};
529
530     pXRenderSetPictureTransform(gdi_display, src_pict, &xform);
531 #endif
532 }
533
534 /* check if we can use repeating instead of scaling for the specified source DC */
535 static BOOL use_source_repeat( X11DRV_PDEVICE *physDev )
536 {
537     return (physDev->bitmap &&
538             physDev->drawable_rect.right - physDev->drawable_rect.left == 1 &&
539             physDev->drawable_rect.bottom - physDev->drawable_rect.top == 1);
540 }
541
542 static struct xrender_info *get_xrender_info(X11DRV_PDEVICE *physDev)
543 {
544     if(!physDev->xrender)
545     {
546         physDev->xrender = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev->xrender));
547
548         if(!physDev->xrender)
549         {
550             ERR("Unable to allocate XRENDERINFO!\n");
551             return NULL;
552         }
553         physDev->xrender->cache_index = -1;
554     }
555     if (!physDev->xrender->format)
556         physDev->xrender->format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
557
558     return physDev->xrender;
559 }
560
561 static Picture get_xrender_picture(X11DRV_PDEVICE *physDev)
562 {
563     struct xrender_info *info = get_xrender_info(physDev);
564     if (!info) return 0;
565
566     if (!info->pict && info->format)
567     {
568         XRenderPictureAttributes pa;
569         RGNDATA *clip = X11DRV_GetRegionData( physDev->region, 0 );
570
571         wine_tsx11_lock();
572         pa.subwindow_mode = IncludeInferiors;
573         info->pict = pXRenderCreatePicture(gdi_display, physDev->drawable, info->format->pict_format,
574                                            CPSubwindowMode, &pa);
575         if (info->pict && clip)
576             pXRenderSetPictureClipRectangles( gdi_display, info->pict,
577                                               physDev->dc_rect.left, physDev->dc_rect.top,
578                                               (XRectangle *)clip->Buffer, clip->rdh.nCount );
579         wine_tsx11_unlock();
580         TRACE("Allocing pict=%lx dc=%p drawable=%08lx\n", info->pict, physDev->hdc, physDev->drawable);
581         HeapFree( GetProcessHeap(), 0, clip );
582     }
583
584     return info->pict;
585 }
586
587 static Picture get_xrender_picture_source(X11DRV_PDEVICE *physDev, BOOL repeat)
588 {
589     struct xrender_info *info = get_xrender_info(physDev);
590     if (!info) return 0;
591
592     if (!info->pict_src && info->format)
593     {
594         XRenderPictureAttributes pa;
595
596         wine_tsx11_lock();
597         pa.subwindow_mode = IncludeInferiors;
598         pa.repeat = repeat ? RepeatNormal : RepeatNone;
599         info->pict_src = pXRenderCreatePicture(gdi_display, physDev->drawable, info->format->pict_format,
600                                                CPSubwindowMode|CPRepeat, &pa);
601         wine_tsx11_unlock();
602
603         TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
604               info->pict_src, physDev->hdc, physDev->drawable, pa.repeat);
605     }
606
607     return info->pict_src;
608 }
609
610 /* return a mask picture used to force alpha to 0 */
611 static Picture get_no_alpha_mask(void)
612 {
613     static Pixmap pixmap;
614     static Picture pict;
615
616     wine_tsx11_lock();
617     if (!pict)
618     {
619         const WineXRenderFormat *fmt = get_xrender_format( WXR_FORMAT_A8R8G8B8 );
620         XRenderPictureAttributes pa;
621         XRenderColor col;
622
623         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
624         pa.repeat = RepeatNormal;
625         pa.component_alpha = True;
626         pict = pXRenderCreatePicture( gdi_display, pixmap, fmt->pict_format,
627                                       CPRepeat|CPComponentAlpha, &pa );
628         col.red = col.green = col.blue = 0xffff;
629         col.alpha = 0;
630         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
631     }
632     wine_tsx11_unlock();
633     return pict;
634 }
635
636 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
637 {
638   if(p1->hash != p2->hash) return TRUE;
639   if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE;
640   if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE;
641   if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
642   return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName);
643 }
644
645 #if 0
646 static void walk_cache(void)
647 {
648   int i;
649
650   EnterCriticalSection(&xrender_cs);
651   for(i=mru; i >= 0; i = glyphsetCache[i].next)
652     TRACE("item %d\n", i);
653   LeaveCriticalSection(&xrender_cs);
654 }
655 #endif
656
657 static int LookupEntry(LFANDSIZE *plfsz)
658 {
659   int i, prev_i = -1;
660
661   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
662     TRACE("%d\n", i);
663     if(glyphsetCache[i].count == -1) { /* reached free list so stop */
664       i = -1;
665       break;
666     }
667
668     if(!fontcmp(&glyphsetCache[i].lfsz, plfsz)) {
669       glyphsetCache[i].count++;
670       if(prev_i >= 0) {
671         glyphsetCache[prev_i].next = glyphsetCache[i].next;
672         glyphsetCache[i].next = mru;
673         mru = i;
674       }
675       TRACE("found font in cache %d\n", i);
676       return i;
677     }
678     prev_i = i;
679   }
680   TRACE("font not in cache\n");
681   return -1;
682 }
683
684 static void FreeEntry(int entry)
685 {
686     int i, format;
687   
688     for(format = 0; format < AA_MAXVALUE; format++) {
689         gsCacheEntryFormat * formatEntry;
690
691         if( !glyphsetCache[entry].format[format] )
692             continue;
693
694         formatEntry = glyphsetCache[entry].format[format];
695
696         if(formatEntry->glyphset) {
697             wine_tsx11_lock();
698             pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
699             wine_tsx11_unlock();
700             formatEntry->glyphset = 0;
701         }
702         if(formatEntry->nrealized) {
703             HeapFree(GetProcessHeap(), 0, formatEntry->realized);
704             formatEntry->realized = NULL;
705             if(formatEntry->bitmaps) {
706                 for(i = 0; i < formatEntry->nrealized; i++)
707                     HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps[i]);
708                 HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps);
709                 formatEntry->bitmaps = NULL;
710             }
711             HeapFree(GetProcessHeap(), 0, formatEntry->gis);
712             formatEntry->gis = NULL;
713             formatEntry->nrealized = 0;
714         }
715
716         HeapFree(GetProcessHeap(), 0, formatEntry);
717         glyphsetCache[entry].format[format] = NULL;
718     }
719 }
720
721 static int AllocEntry(void)
722 {
723   int best = -1, prev_best = -1, i, prev_i = -1;
724
725   if(lastfree >= 0) {
726     assert(glyphsetCache[lastfree].count == -1);
727     glyphsetCache[lastfree].count = 1;
728     best = lastfree;
729     lastfree = glyphsetCache[lastfree].next;
730     assert(best != mru);
731     glyphsetCache[best].next = mru;
732     mru = best;
733
734     TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
735     return mru;
736   }
737
738   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
739     if(glyphsetCache[i].count == 0) {
740       best = i;
741       prev_best = prev_i;
742     }
743     prev_i = i;
744   }
745
746   if(best >= 0) {
747     TRACE("freeing unused glyphset at cache %d\n", best);
748     FreeEntry(best);
749     glyphsetCache[best].count = 1;
750     if(prev_best >= 0) {
751       glyphsetCache[prev_best].next = glyphsetCache[best].next;
752       glyphsetCache[best].next = mru;
753       mru = best;
754     } else {
755       assert(mru == best);
756     }
757     return mru;
758   }
759
760   TRACE("Growing cache\n");
761   
762   if (glyphsetCache)
763     glyphsetCache = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
764                               glyphsetCache,
765                               (glyphsetCacheSize + INIT_CACHE_SIZE)
766                               * sizeof(*glyphsetCache));
767   else
768     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
769                               (glyphsetCacheSize + INIT_CACHE_SIZE)
770                               * sizeof(*glyphsetCache));
771
772   for(best = i = glyphsetCacheSize; i < glyphsetCacheSize + INIT_CACHE_SIZE;
773       i++) {
774     glyphsetCache[i].next = i + 1;
775     glyphsetCache[i].count = -1;
776   }
777   glyphsetCache[i-1].next = -1;
778   glyphsetCacheSize += INIT_CACHE_SIZE;
779
780   lastfree = glyphsetCache[best].next;
781   glyphsetCache[best].count = 1;
782   glyphsetCache[best].next = mru;
783   mru = best;
784   TRACE("new free cache slot at %d\n", mru);
785   return mru;
786 }
787
788 static BOOL get_gasp_flags(X11DRV_PDEVICE *physDev, WORD *flags)
789 {
790     DWORD size;
791     WORD *gasp, *buffer;
792     WORD num_recs;
793     DWORD ppem;
794     TEXTMETRICW tm;
795
796     *flags = 0;
797
798     size = GetFontData(physDev->hdc, MS_GASP_TAG,  0, NULL, 0);
799     if(size == GDI_ERROR)
800         return FALSE;
801
802     gasp = buffer = HeapAlloc(GetProcessHeap(), 0, size);
803     GetFontData(physDev->hdc, MS_GASP_TAG,  0, gasp, size);
804
805     GetTextMetricsW(physDev->hdc, &tm);
806     ppem = abs(X11DRV_YWStoDS(physDev, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading));
807
808     gasp++;
809     num_recs = get_be_word(*gasp);
810     gasp++;
811     while(num_recs--)
812     {
813         *flags = get_be_word(*(gasp + 1));
814         if(ppem <= get_be_word(*gasp))
815             break;
816         gasp += 2;
817     }
818     TRACE("got flags %04x for ppem %d\n", *flags, ppem);
819
820     HeapFree(GetProcessHeap(), 0, buffer);
821     return TRUE;
822 }
823
824 static AA_Type get_antialias_type( X11DRV_PDEVICE *physDev, BOOL subpixel, BOOL hinter)
825 {
826     AA_Type ret;
827     WORD flags;
828     UINT font_smoothing_type, font_smoothing_orientation;
829
830     if (X11DRV_XRender_Installed && subpixel &&
831         SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE, 0, &font_smoothing_type, 0) &&
832         font_smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
833     {
834         if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION, 0,
835                                     &font_smoothing_orientation, 0) &&
836              font_smoothing_orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
837         {
838             ret = AA_BGR;
839         }
840         else
841             ret = AA_RGB;
842         /*FIXME
843           If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
844           But, Wine's subpixel rendering can support the portrait mode.
845          */
846     }
847     else if (!hinter || !get_gasp_flags(physDev, &flags) || flags & GASP_DOGRAY)
848         ret = AA_Grey;
849     else
850         ret = AA_None;
851
852     return ret;
853 }
854
855 static int GetCacheEntry(X11DRV_PDEVICE *physDev, LFANDSIZE *plfsz)
856 {
857     int ret;
858     int format;
859     gsCacheEntry *entry;
860     static int hinter = -1;
861     static int subpixel = -1;
862     BOOL font_smoothing;
863
864     if((ret = LookupEntry(plfsz)) != -1) return ret;
865
866     ret = AllocEntry();
867     entry = glyphsetCache + ret;
868     entry->lfsz = *plfsz;
869     for( format = 0; format < AA_MAXVALUE; format++ ) {
870         assert( !entry->format[format] );
871     }
872
873     if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY)
874     {
875         if(hinter == -1 || subpixel == -1)
876         {
877             RASTERIZER_STATUS status;
878             GetRasterizerCaps(&status, sizeof(status));
879             hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
880             subpixel = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
881         }
882
883         switch (plfsz->lf.lfQuality)
884         {
885             case ANTIALIASED_QUALITY:
886                 entry->aa_default = get_antialias_type( physDev, FALSE, hinter );
887                 break;
888             case CLEARTYPE_QUALITY:
889             case CLEARTYPE_NATURAL_QUALITY:
890                 entry->aa_default = get_antialias_type( physDev, subpixel, hinter );
891                 break;
892             case DEFAULT_QUALITY:
893             case DRAFT_QUALITY:
894             case PROOF_QUALITY:
895             default:
896                 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0) &&
897                      font_smoothing)
898                 {
899                     entry->aa_default = get_antialias_type( physDev, subpixel, hinter );
900                 }
901                 else
902                     entry->aa_default = AA_None;
903                 break;
904         }
905
906 #ifdef SONAME_LIBFONTCONFIG
907         if (fontconfig_installed)
908         {
909             FcPattern *match, *pattern = pFcPatternCreate();
910             FcResult result;
911             char family[LF_FACESIZE * 4];
912
913             WideCharToMultiByte( CP_UTF8, 0, plfsz->lf.lfFaceName, -1, family, sizeof(family), NULL, NULL );
914             pFcPatternAddString( pattern, FC_FAMILY, (FcChar8 *)family );
915             if (plfsz->lf.lfWeight != FW_DONTCARE)
916             {
917                 int weight;
918                 switch (plfsz->lf.lfWeight)
919                 {
920                 case FW_THIN:       weight = FC_WEIGHT_THIN; break;
921                 case FW_EXTRALIGHT: weight = FC_WEIGHT_EXTRALIGHT; break;
922                 case FW_LIGHT:      weight = FC_WEIGHT_LIGHT; break;
923                 case FW_NORMAL:     weight = FC_WEIGHT_NORMAL; break;
924                 case FW_MEDIUM:     weight = FC_WEIGHT_MEDIUM; break;
925                 case FW_SEMIBOLD:   weight = FC_WEIGHT_SEMIBOLD; break;
926                 case FW_BOLD:       weight = FC_WEIGHT_BOLD; break;
927                 case FW_EXTRABOLD:  weight = FC_WEIGHT_EXTRABOLD; break;
928                 case FW_HEAVY:      weight = FC_WEIGHT_HEAVY; break;
929                 default:            weight = (plfsz->lf.lfWeight - 80) / 4; break;
930                 }
931                 pFcPatternAddInteger( pattern, FC_WEIGHT, weight );
932             }
933             pFcPatternAddInteger( pattern, FC_SLANT, plfsz->lf.lfItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
934             pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
935             pFcDefaultSubstitute( pattern );
936             if ((match = pFcFontMatch( NULL, pattern, &result )))
937             {
938                 int rgba;
939
940                 if (pFcPatternGetInteger( match, FC_RGBA, 0, &rgba ) == FcResultMatch)
941                 {
942                     FcChar8 *file;
943                     if (pFcPatternGetString( match, FC_FILE, 0, &file ) != FcResultMatch) file = NULL;
944
945                     TRACE( "fontconfig returned rgba %u for font %s file %s\n",
946                          rgba, debugstr_w(plfsz->lf.lfFaceName), debugstr_a((char *)file) );
947
948                     switch (rgba)
949                     {
950                     case FC_RGBA_RGB:  entry->aa_default = AA_RGB; break;
951                     case FC_RGBA_BGR:  entry->aa_default = AA_BGR; break;
952                     case FC_RGBA_VRGB: entry->aa_default = AA_VRGB; break;
953                     case FC_RGBA_VBGR: entry->aa_default = AA_VBGR; break;
954                     case FC_RGBA_NONE: entry->aa_default = AA_None; break;
955                     }
956                 }
957                 pFcPatternDestroy( match );
958             }
959             pFcPatternDestroy( pattern );
960         }
961 #endif  /* SONAME_LIBFONTCONFIG */
962     }
963     else
964         entry->aa_default = AA_None;
965
966     return ret;
967 }
968
969 static void dec_ref_cache(int index)
970 {
971     assert(index >= 0);
972     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
973     assert(glyphsetCache[index].count > 0);
974     glyphsetCache[index].count--;
975 }
976
977 static void lfsz_calc_hash(LFANDSIZE *plfsz)
978 {
979   DWORD hash = 0, *ptr, two_chars;
980   WORD *pwc;
981   int i;
982
983   hash ^= plfsz->devsize.cx;
984   hash ^= plfsz->devsize.cy;
985   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
986     hash ^= *ptr;
987   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
988     hash ^= *ptr;
989   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
990     two_chars = *ptr;
991     pwc = (WCHAR *)&two_chars;
992     if(!*pwc) break;
993     *pwc = toupperW(*pwc);
994     pwc++;
995     *pwc = toupperW(*pwc);
996     hash ^= two_chars;
997     if(!*pwc) break;
998   }
999   plfsz->hash = hash;
1000   return;
1001 }
1002
1003 /***********************************************************************
1004  *   X11DRV_XRender_Finalize
1005  */
1006 void X11DRV_XRender_Finalize(void)
1007 {
1008     int i;
1009
1010     EnterCriticalSection(&xrender_cs);
1011     for(i = mru; i >= 0; i = glyphsetCache[i].next)
1012         FreeEntry(i);
1013     LeaveCriticalSection(&xrender_cs);
1014 }
1015
1016
1017 /***********************************************************************
1018  *   X11DRV_XRender_SelectFont
1019  */
1020 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
1021 {
1022     LFANDSIZE lfsz;
1023     struct xrender_info *info;
1024
1025     GetObjectW(hfont, sizeof(lfsz.lf), &lfsz.lf);
1026     TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1027           lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
1028           lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
1029     lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
1030     lfsz.devsize.cx = X11DRV_XWStoDS( physDev, lfsz.lf.lfWidth );
1031     lfsz.devsize.cy = X11DRV_YWStoDS( physDev, lfsz.lf.lfHeight );
1032     GetWorldTransform( physDev->hdc, &lfsz.xform );
1033     lfsz_calc_hash(&lfsz);
1034
1035     info = get_xrender_info(physDev);
1036     if (!info) return 0;
1037
1038     EnterCriticalSection(&xrender_cs);
1039     if(info->cache_index != -1)
1040         dec_ref_cache(info->cache_index);
1041     info->cache_index = GetCacheEntry(physDev, &lfsz);
1042     LeaveCriticalSection(&xrender_cs);
1043     return 0;
1044 }
1045
1046 /***********************************************************************
1047 *   X11DRV_XRender_SetDeviceClipping
1048 */
1049 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
1050 {
1051     if (physDev->xrender->pict)
1052     {
1053         wine_tsx11_lock();
1054         pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
1055                                           physDev->dc_rect.left, physDev->dc_rect.top,
1056                                           (XRectangle *)data->Buffer, data->rdh.nCount );
1057         wine_tsx11_unlock();
1058     }
1059 }
1060
1061 /***********************************************************************
1062  *   X11DRV_XRender_DeleteDC
1063  */
1064 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
1065 {
1066     X11DRV_XRender_UpdateDrawable(physDev);
1067
1068     EnterCriticalSection(&xrender_cs);
1069     if(physDev->xrender->cache_index != -1)
1070         dec_ref_cache(physDev->xrender->cache_index);
1071     LeaveCriticalSection(&xrender_cs);
1072
1073     HeapFree(GetProcessHeap(), 0, physDev->xrender);
1074     physDev->xrender = NULL;
1075     return;
1076 }
1077
1078 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
1079 {
1080     const WineXRenderFormat *fmt;
1081     ColorShifts shifts;
1082
1083     /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1084      * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1085      * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1086     if (!X11DRV_XRender_Installed || bits_pixel <= 8)
1087         return FALSE;
1088
1089     if (dib)
1090     {
1091         X11DRV_PALETTE_ComputeColorShifts(&shifts, dib->dsBitfields[0], dib->dsBitfields[1], dib->dsBitfields[2]);
1092         fmt = get_xrender_format_from_color_shifts(dib->dsBm.bmBitsPixel, &shifts);
1093
1094         /* Common formats should be in our picture format table. */
1095         if (!fmt)
1096         {
1097             TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1098                 dib->dsBm.bmBitsPixel, dib->dsBitfields[0], dib->dsBitfields[1], dib->dsBitfields[2]);
1099             return FALSE;
1100         }
1101     }
1102     else
1103     {
1104         int red_mask, green_mask, blue_mask;
1105
1106         /* We are dealing with a DDB */
1107         switch (bits_pixel)
1108         {
1109             case 16:
1110                 fmt = get_xrender_format(WXR_FORMAT_R5G6B5);
1111                 break;
1112             case 24:
1113                 fmt = get_xrender_format(WXR_FORMAT_R8G8B8);
1114                 break;
1115             case 32:
1116                 fmt = get_xrender_format(WXR_FORMAT_A8R8G8B8);
1117                 break;
1118             default:
1119                 fmt = NULL;
1120         }
1121
1122         if (!fmt)
1123         {
1124             TRACE("Unhandled DDB bits_pixel=%d\n", bits_pixel);
1125             return FALSE;
1126         }
1127
1128         red_mask = fmt->pict_format->direct.redMask << fmt->pict_format->direct.red;
1129         green_mask = fmt->pict_format->direct.greenMask << fmt->pict_format->direct.green;
1130         blue_mask = fmt->pict_format->direct.blueMask << fmt->pict_format->direct.blue;
1131         X11DRV_PALETTE_ComputeColorShifts(&shifts, red_mask, green_mask, blue_mask);
1132     }
1133
1134     physBitmap->pixmap_depth = fmt->pict_format->depth;
1135     physBitmap->trueColor = TRUE;
1136     physBitmap->pixmap_color_shifts = shifts;
1137     return TRUE;
1138 }
1139
1140 /***********************************************************************
1141  *   X11DRV_XRender_UpdateDrawable
1142  *
1143  * Deletes the pict and tile when the drawable changes.
1144  */
1145 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
1146 {
1147     struct xrender_info *info = physDev->xrender;
1148
1149     if (info->pict || info->pict_src)
1150     {
1151         wine_tsx11_lock();
1152         XFlush( gdi_display );
1153         if (info->pict)
1154         {
1155             TRACE("freeing pict = %lx dc = %p\n", info->pict, physDev->hdc);
1156             pXRenderFreePicture(gdi_display, info->pict);
1157             info->pict = 0;
1158         }
1159         if(info->pict_src)
1160         {
1161             TRACE("freeing pict = %lx dc = %p\n", info->pict_src, physDev->hdc);
1162             pXRenderFreePicture(gdi_display, info->pict_src);
1163             info->pict_src = 0;
1164         }
1165         wine_tsx11_unlock();
1166     }
1167
1168     info->format = NULL;
1169 }
1170
1171 /************************************************************************
1172  *   UploadGlyph
1173  *
1174  * Helper to ExtTextOut.  Must be called inside xrender_cs
1175  */
1176 static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
1177 {
1178     unsigned int buflen;
1179     char *buf;
1180     Glyph gid;
1181     GLYPHMETRICS gm;
1182     XGlyphInfo gi;
1183     gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
1184     gsCacheEntryFormat *formatEntry;
1185     UINT ggo_format = GGO_GLYPH_INDEX;
1186     WXRFormat wxr_format;
1187     static const char zero[4];
1188     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1189
1190     switch(format) {
1191     case AA_Grey:
1192         ggo_format |= WINE_GGO_GRAY16_BITMAP;
1193         break;
1194     case AA_RGB:
1195         ggo_format |= WINE_GGO_HRGB_BITMAP;
1196         break;
1197     case AA_BGR:
1198         ggo_format |= WINE_GGO_HBGR_BITMAP;
1199         break;
1200     case AA_VRGB:
1201         ggo_format |= WINE_GGO_VRGB_BITMAP;
1202         break;
1203     case AA_VBGR:
1204         ggo_format |= WINE_GGO_VBGR_BITMAP;
1205         break;
1206
1207     default:
1208         ERR("aa = %d - not implemented\n", format);
1209     case AA_None:
1210         ggo_format |= GGO_BITMAP;
1211         break;
1212     }
1213
1214     buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1215     if(buflen == GDI_ERROR) {
1216         if(format != AA_None) {
1217             format = AA_None;
1218             entry->aa_default = AA_None;
1219             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1220             buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1221         }
1222         if(buflen == GDI_ERROR) {
1223             WARN("GetGlyphOutlineW failed\n");
1224             return FALSE;
1225         }
1226         TRACE("Turning off antialiasing for this monochrome font\n");
1227     }
1228
1229     /* If there is nothing for the current type, we create the entry. */
1230     if( !entry->format[format] ) {
1231         entry->format[format] = HeapAlloc(GetProcessHeap(),
1232                                           HEAP_ZERO_MEMORY,
1233                                           sizeof(gsCacheEntryFormat));
1234     }
1235     formatEntry = entry->format[format];
1236
1237     if(formatEntry->nrealized <= glyph) {
1238         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1239
1240         if (formatEntry->realized)
1241             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1242                                       HEAP_ZERO_MEMORY,
1243                                       formatEntry->realized,
1244                                       formatEntry->nrealized * sizeof(BOOL));
1245         else
1246             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1247                                       HEAP_ZERO_MEMORY,
1248                                       formatEntry->nrealized * sizeof(BOOL));
1249
1250         if(!X11DRV_XRender_Installed) {
1251           if (formatEntry->bitmaps)
1252             formatEntry->bitmaps = HeapReAlloc(GetProcessHeap(),
1253                                       HEAP_ZERO_MEMORY,
1254                                       formatEntry->bitmaps,
1255                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1256           else
1257             formatEntry->bitmaps = HeapAlloc(GetProcessHeap(),
1258                                       HEAP_ZERO_MEMORY,
1259                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1260         }
1261         if (formatEntry->gis)
1262             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1263                                    HEAP_ZERO_MEMORY,
1264                                    formatEntry->gis,
1265                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1266         else
1267             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1268                                    HEAP_ZERO_MEMORY,
1269                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1270     }
1271
1272
1273     if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
1274         switch(format) {
1275             case AA_Grey:
1276                 wxr_format = WXR_FORMAT_GRAY;
1277                 break;
1278
1279             case AA_RGB:
1280             case AA_BGR:
1281             case AA_VRGB:
1282             case AA_VBGR:
1283                 wxr_format = WXR_FORMAT_A8R8G8B8;
1284                 break;
1285
1286             default:
1287                 ERR("aa = %d - not implemented\n", format);
1288             case AA_None:
1289                 wxr_format = WXR_FORMAT_MONO;
1290                 break;
1291         }
1292
1293         wine_tsx11_lock();
1294         formatEntry->font_format = get_xrender_format(wxr_format);
1295         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format->pict_format);
1296         wine_tsx11_unlock();
1297     }
1298
1299
1300     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1301     GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1302     formatEntry->realized[glyph] = TRUE;
1303
1304     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1305           buflen,
1306           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1307           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1308
1309     gi.width = gm.gmBlackBoxX;
1310     gi.height = gm.gmBlackBoxY;
1311     gi.x = -gm.gmptGlyphOrigin.x;
1312     gi.y = gm.gmptGlyphOrigin.y;
1313     gi.xOff = gm.gmCellIncX;
1314     gi.yOff = gm.gmCellIncY;
1315
1316     if(TRACE_ON(xrender)) {
1317         int pitch, i, j;
1318         char output[300];
1319         unsigned char *line;
1320
1321         if(format == AA_None) {
1322             pitch = ((gi.width + 31) / 32) * 4;
1323             for(i = 0; i < gi.height; i++) {
1324                 line = (unsigned char*) buf + i * pitch;
1325                 output[0] = '\0';
1326                 for(j = 0; j < pitch * 8; j++) {
1327                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1328                 }
1329                 TRACE("%s\n", output);
1330             }
1331         } else {
1332             static const char blks[] = " .:;!o*#";
1333             char str[2];
1334
1335             str[1] = '\0';
1336             pitch = ((gi.width + 3) / 4) * 4;
1337             for(i = 0; i < gi.height; i++) {
1338                 line = (unsigned char*) buf + i * pitch;
1339                 output[0] = '\0';
1340                 for(j = 0; j < pitch; j++) {
1341                     str[0] = blks[line[j] >> 5];
1342                     strcat(output, str);
1343                 }
1344                 TRACE("%s\n", output);
1345             }
1346         }
1347     }
1348
1349
1350     if(formatEntry->glyphset) {
1351         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1352             unsigned char *byte = (unsigned char*) buf, c;
1353             int i = buflen;
1354
1355             while(i--) {
1356                 c = *byte;
1357
1358                 /* magic to flip bit order */
1359                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1360                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1361                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1362
1363                 *byte++ = c;
1364             }
1365         }
1366         else if ( format != AA_Grey &&
1367                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1368         {
1369             unsigned int i, *data = (unsigned int *)buf;
1370             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1371         }
1372         gid = glyph;
1373
1374         /*
1375           XRenderCompositeText seems to ignore 0x0 glyphs when
1376           AA_None, which means we lose the advance width of glyphs
1377           like the space.  We'll pretend that such glyphs are 1x1
1378           bitmaps.
1379         */
1380
1381         if(buflen == 0)
1382             gi.width = gi.height = 1;
1383
1384         wine_tsx11_lock();
1385         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1386                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1387         wine_tsx11_unlock();
1388         HeapFree(GetProcessHeap(), 0, buf);
1389     } else {
1390         formatEntry->bitmaps[glyph] = buf;
1391     }
1392
1393     formatEntry->gis[glyph] = gi;
1394
1395     return TRUE;
1396 }
1397
1398 static void SharpGlyphMono(X11DRV_PDEVICE *physDev, INT x, INT y,
1399                             void *bitmap, XGlyphInfo *gi)
1400 {
1401     unsigned char   *srcLine = bitmap, *src;
1402     unsigned char   bits, bitsMask;
1403     int             width = gi->width;
1404     int             stride = ((width + 31) & ~31) >> 3;
1405     int             height = gi->height;
1406     int             w;
1407     int             xspan, lenspan;
1408
1409     TRACE("%d, %d\n", x, y);
1410     x -= gi->x;
1411     y -= gi->y;
1412     while (height--)
1413     {
1414         src = srcLine;
1415         srcLine += stride;
1416         w = width;
1417         
1418         bitsMask = 0x80;    /* FreeType is always MSB first */
1419         bits = *src++;
1420         
1421         xspan = x;
1422         while (w)
1423         {
1424             if (bits & bitsMask)
1425             {
1426                 lenspan = 0;
1427                 do
1428                 {
1429                     lenspan++;
1430                     if (lenspan == w)
1431                         break;
1432                     bitsMask = bitsMask >> 1;
1433                     if (!bitsMask)
1434                     {
1435                         bits = *src++;
1436                         bitsMask = 0x80;
1437                     }
1438                 } while (bits & bitsMask);
1439                 XFillRectangle (gdi_display, physDev->drawable, 
1440                                 physDev->gc, xspan, y, lenspan, 1);
1441                 xspan += lenspan;
1442                 w -= lenspan;
1443             }
1444             else
1445             {
1446                 do
1447                 {
1448                     w--;
1449                     xspan++;
1450                     if (!w)
1451                         break;
1452                     bitsMask = bitsMask >> 1;
1453                     if (!bitsMask)
1454                     {
1455                         bits = *src++;
1456                         bitsMask = 0x80;
1457                     }
1458                 } while (!(bits & bitsMask));
1459             }
1460         }
1461         y++;
1462     }
1463 }
1464
1465 static void SharpGlyphGray(X11DRV_PDEVICE *physDev, INT x, INT y,
1466                             void *bitmap, XGlyphInfo *gi)
1467 {
1468     unsigned char   *srcLine = bitmap, *src, bits;
1469     int             width = gi->width;
1470     int             stride = ((width + 3) & ~3);
1471     int             height = gi->height;
1472     int             w;
1473     int             xspan, lenspan;
1474
1475     x -= gi->x;
1476     y -= gi->y;
1477     while (height--)
1478     {
1479         src = srcLine;
1480         srcLine += stride;
1481         w = width;
1482         
1483         bits = *src++;
1484         xspan = x;
1485         while (w)
1486         {
1487             if (bits >= 0x80)
1488             {
1489                 lenspan = 0;
1490                 do
1491                 {
1492                     lenspan++;
1493                     if (lenspan == w)
1494                         break;
1495                     bits = *src++;
1496                 } while (bits >= 0x80);
1497                 XFillRectangle (gdi_display, physDev->drawable, 
1498                                 physDev->gc, xspan, y, lenspan, 1);
1499                 xspan += lenspan;
1500                 w -= lenspan;
1501             }
1502             else
1503             {
1504                 do
1505                 {
1506                     w--;
1507                     xspan++;
1508                     if (!w)
1509                         break;
1510                     bits = *src++;
1511                 } while (bits < 0x80);
1512             }
1513         }
1514         y++;
1515     }
1516 }
1517
1518
1519 static void ExamineBitfield (DWORD mask, int *shift, int *len)
1520 {
1521     int s, l;
1522
1523     s = 0;
1524     while ((mask & 1) == 0)
1525     {
1526         mask >>= 1;
1527         s++;
1528     }
1529     l = 0;
1530     while ((mask & 1) == 1)
1531     {
1532         mask >>= 1;
1533         l++;
1534     }
1535     *shift = s;
1536     *len = l;
1537 }
1538
1539 static DWORD GetField (DWORD pixel, int shift, int len)
1540 {
1541     pixel = pixel & (((1 << (len)) - 1) << shift);
1542     pixel = pixel << (32 - (shift + len)) >> 24;
1543     while (len < 8)
1544     {
1545         pixel |= (pixel >> len);
1546         len <<= 1;
1547     }
1548     return pixel;
1549 }
1550
1551
1552 static DWORD PutField (DWORD pixel, int shift, int len)
1553 {
1554     shift = shift - (8 - len);
1555     if (len <= 8)
1556         pixel &= (((1 << len) - 1) << (8 - len));
1557     if (shift < 0)
1558         pixel >>= -shift;
1559     else
1560         pixel <<= shift;
1561     return pixel;
1562 }
1563
1564 static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInfo *gi,
1565                             int color)
1566 {
1567     int             r_shift, r_len;
1568     int             g_shift, g_len;
1569     int             b_shift, b_len;
1570     BYTE            *maskLine, *mask, m;
1571     int             maskStride;
1572     DWORD           pixel;
1573     int             width, height;
1574     int             w, tx;
1575     BYTE            src_r, src_g, src_b;
1576
1577     x -= gi->x;
1578     y -= gi->y;
1579     width = gi->width;
1580     height = gi->height;
1581
1582     maskLine = bitmap;
1583     maskStride = (width + 3) & ~3;
1584
1585     ExamineBitfield (image->red_mask, &r_shift, &r_len);
1586     ExamineBitfield (image->green_mask, &g_shift, &g_len);
1587     ExamineBitfield (image->blue_mask, &b_shift, &b_len);
1588
1589     src_r = GetField(color, r_shift, r_len);
1590     src_g = GetField(color, g_shift, g_len);
1591     src_b = GetField(color, b_shift, b_len);
1592     
1593     for(; height--; y++)
1594     {
1595         mask = maskLine;
1596         maskLine += maskStride;
1597         w = width;
1598         tx = x;
1599
1600         if(y < 0) continue;
1601         if(y >= image->height) break;
1602
1603         for(; w--; tx++)
1604         {
1605             if(tx >= image->width) break;
1606
1607             m = *mask++;
1608             if(tx < 0) continue;
1609
1610             if (m == 0xff)
1611                 XPutPixel (image, tx, y, color);
1612             else if (m)
1613             {
1614                 BYTE r, g, b;
1615
1616                 pixel = XGetPixel (image, tx, y);
1617
1618                 r = GetField(pixel, r_shift, r_len);
1619                 r = ((BYTE)~m * (WORD)r + (BYTE)m * (WORD)src_r) >> 8;
1620                 g = GetField(pixel, g_shift, g_len);
1621                 g = ((BYTE)~m * (WORD)g + (BYTE)m * (WORD)src_g) >> 8;
1622                 b = GetField(pixel, b_shift, b_len);
1623                 b = ((BYTE)~m * (WORD)b + (BYTE)m * (WORD)src_b) >> 8;
1624
1625                 pixel = (PutField (r, r_shift, r_len) |
1626                          PutField (g, g_shift, g_len) |
1627                          PutField (b, b_shift, b_len));
1628                 XPutPixel (image, tx, y, pixel);
1629             }
1630         }
1631     }
1632 }
1633
1634 /*************************************************************
1635  *                 get_tile_pict
1636  *
1637  * Returns an appropriate Picture for tiling the text colour.
1638  * Call and use result within the xrender_cs
1639  */
1640 static Picture get_tile_pict(const WineXRenderFormat *wxr_format, int text_pixel)
1641 {
1642     static struct
1643     {
1644         Pixmap xpm;
1645         Picture pict;
1646         int current_color;
1647     } tiles[WXR_NB_FORMATS], *tile;
1648     XRenderColor col;
1649
1650     tile = &tiles[wxr_format->format];
1651
1652     if(!tile->xpm)
1653     {
1654         XRenderPictureAttributes pa;
1655
1656         wine_tsx11_lock();
1657         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, wxr_format->pict_format->depth);
1658
1659         pa.repeat = RepeatNormal;
1660         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, wxr_format->pict_format, CPRepeat, &pa);
1661         wine_tsx11_unlock();
1662
1663         /* init current_color to something different from text_pixel */
1664         tile->current_color = ~text_pixel;
1665
1666         if(wxr_format->format == WXR_FORMAT_MONO)
1667         {
1668             /* for a 1bpp bitmap we always need a 1 in the tile */
1669             col.red = col.green = col.blue = 0;
1670             col.alpha = 0xffff;
1671             wine_tsx11_lock();
1672             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1673             wine_tsx11_unlock();
1674         }
1675     }
1676
1677     if(text_pixel != tile->current_color && wxr_format->format != WXR_FORMAT_MONO)
1678     {
1679         get_xrender_color(wxr_format, text_pixel, &col);
1680         wine_tsx11_lock();
1681         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1682         wine_tsx11_unlock();
1683         tile->current_color = text_pixel;
1684     }
1685     return tile->pict;
1686 }
1687
1688 /*************************************************************
1689  *                 get_mask_pict
1690  *
1691  * Returns an appropriate Picture for masking with the specified alpha.
1692  * Call and use result within the xrender_cs
1693  */
1694 static Picture get_mask_pict( int alpha )
1695 {
1696     static Pixmap pixmap;
1697     static Picture pict;
1698     static int current_alpha;
1699
1700     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1701
1702     if (!pixmap)
1703     {
1704         const WineXRenderFormat *fmt = get_xrender_format( WXR_FORMAT_A8R8G8B8 );
1705         XRenderPictureAttributes pa;
1706
1707         wine_tsx11_lock();
1708         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1709         pa.repeat = RepeatNormal;
1710         pict = pXRenderCreatePicture( gdi_display, pixmap, fmt->pict_format, CPRepeat, &pa );
1711         wine_tsx11_unlock();
1712         current_alpha = -1;
1713     }
1714
1715     if (alpha != current_alpha)
1716     {
1717         XRenderColor col;
1718         col.red = col.green = col.blue = 0;
1719         col.alpha = current_alpha = alpha;
1720         wine_tsx11_lock();
1721         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1722         wine_tsx11_unlock();
1723     }
1724     return pict;
1725 }
1726
1727 static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
1728 {
1729     return 1;
1730 }
1731
1732 /***********************************************************************
1733  *   X11DRV_XRender_ExtTextOut
1734  */
1735 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
1736                                 const RECT *lprect, LPCWSTR wstr, UINT count,
1737                                 const INT *lpDx )
1738 {
1739     XGCValues xgcval;
1740     gsCacheEntry *entry;
1741     gsCacheEntryFormat *formatEntry;
1742     BOOL retv = FALSE;
1743     int textPixel, backgroundPixel;
1744     HRGN saved_region = 0;
1745     BOOL disable_antialias = FALSE;
1746     AA_Type aa_type = AA_None;
1747     DIBSECTION bmp;
1748     unsigned int idx;
1749     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
1750     Picture tile_pict = 0;
1751
1752     /* Do we need to disable antialiasing because of palette mode? */
1753     if( !physDev->bitmap || GetObjectW( physDev->bitmap->hbitmap, sizeof(bmp), &bmp ) != sizeof(bmp) ) {
1754         TRACE("bitmap is not a DIB\n");
1755     }
1756     else if (bmp.dsBmih.biBitCount <= 8) {
1757         TRACE("Disabling antialiasing\n");
1758         disable_antialias = TRUE;
1759     }
1760
1761     xgcval.function = GXcopy;
1762     xgcval.background = physDev->backgroundPixel;
1763     xgcval.fill_style = FillSolid;
1764     wine_tsx11_lock();
1765     XChangeGC( gdi_display, physDev->gc, GCFunction | GCBackground | GCFillStyle, &xgcval );
1766     wine_tsx11_unlock();
1767
1768     X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1769
1770     if(physDev->depth == 1) {
1771         if((physDev->textPixel & 0xffffff) == 0) {
1772             textPixel = 0;
1773             backgroundPixel = 1;
1774         } else {
1775             textPixel = 1;
1776             backgroundPixel = 0;
1777         }
1778     } else {
1779         textPixel = physDev->textPixel;
1780         backgroundPixel = physDev->backgroundPixel;
1781     }
1782
1783     if(flags & ETO_OPAQUE)
1784     {
1785         wine_tsx11_lock();
1786         XSetForeground( gdi_display, physDev->gc, backgroundPixel );
1787         XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1788                         physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top,
1789                         lprect->right - lprect->left, lprect->bottom - lprect->top );
1790         wine_tsx11_unlock();
1791     }
1792
1793     if(count == 0)
1794     {
1795         retv = TRUE;
1796         goto done_unlock;
1797     }
1798
1799     if (flags & ETO_CLIPPED)
1800     {
1801         HRGN clip_region;
1802
1803         clip_region = CreateRectRgnIndirect( lprect );
1804         /* make a copy of the current device region */
1805         saved_region = CreateRectRgn( 0, 0, 0, 0 );
1806         CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
1807         X11DRV_SetDeviceClipping( physDev, saved_region, clip_region );
1808         DeleteObject( clip_region );
1809     }
1810
1811     EnterCriticalSection(&xrender_cs);
1812
1813     entry = glyphsetCache + physDev->xrender->cache_index;
1814     if( disable_antialias == FALSE )
1815         aa_type = entry->aa_default;
1816     formatEntry = entry->format[aa_type];
1817
1818     for(idx = 0; idx < count; idx++) {
1819         if( !formatEntry ) {
1820             UploadGlyph(physDev, wstr[idx], aa_type);
1821             /* re-evaluate antialias since aa_default may have changed */
1822             if( disable_antialias == FALSE )
1823                 aa_type = entry->aa_default;
1824             formatEntry = entry->format[aa_type];
1825         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1826             UploadGlyph(physDev, wstr[idx], aa_type);
1827         }
1828     }
1829     if (!formatEntry)
1830     {
1831         WARN("could not upload requested glyphs\n");
1832         LeaveCriticalSection(&xrender_cs);
1833         goto done_unlock;
1834     }
1835
1836     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1837           physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1838
1839     if(X11DRV_XRender_Installed)
1840     {
1841         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1842         POINT offset = {0, 0};
1843         POINT desired, current;
1844         int render_op = PictOpOver;
1845         Picture pict = get_xrender_picture(physDev);
1846
1847         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1848            So we pass zeros to the function and move to our starting position using the first
1849            element of the elts array. */
1850
1851         desired.x = physDev->dc_rect.left + x;
1852         desired.y = physDev->dc_rect.top + y;
1853         current.x = current.y = 0;
1854
1855         tile_pict = get_tile_pict(dst_format, physDev->textPixel);
1856
1857         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1858          */
1859         if((dst_format->format == WXR_FORMAT_MONO) && (textPixel == 0))
1860             render_op = PictOpOutReverse; /* This gives us 'black' text */
1861
1862         for(idx = 0; idx < count; idx++)
1863         {
1864             elts[idx].glyphset = formatEntry->glyphset;
1865             elts[idx].chars = wstr + idx;
1866             elts[idx].nchars = 1;
1867             elts[idx].xOff = desired.x - current.x;
1868             elts[idx].yOff = desired.y - current.y;
1869
1870             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1871             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1872
1873             if(!lpDx)
1874             {
1875                 desired.x += formatEntry->gis[wstr[idx]].xOff;
1876                 desired.y += formatEntry->gis[wstr[idx]].yOff;
1877             }
1878             else
1879             {
1880                 if(flags & ETO_PDY)
1881                 {
1882                     offset.x += lpDx[idx * 2];
1883                     offset.y += lpDx[idx * 2 + 1];
1884                 }
1885                 else
1886                     offset.x += lpDx[idx];
1887                 desired.x = physDev->dc_rect.left + x + offset.x;
1888                 desired.y = physDev->dc_rect.top  + y + offset.y;
1889             }
1890         }
1891         wine_tsx11_lock();
1892         /* Make sure we don't have any transforms set from a previous call */
1893         set_xrender_transformation(pict, 1, 1, 0, 0);
1894         pXRenderCompositeText16(gdi_display, render_op,
1895                                 tile_pict,
1896                                 pict,
1897                                 formatEntry->font_format->pict_format,
1898                                 0, 0, 0, 0, elts, count);
1899         wine_tsx11_unlock();
1900         HeapFree(GetProcessHeap(), 0, elts);
1901     } else {
1902         POINT offset = {0, 0};
1903         wine_tsx11_lock();
1904         XSetForeground( gdi_display, physDev->gc, textPixel );
1905
1906         if(aa_type == AA_None || physDev->depth == 1)
1907         {
1908             void (* sharp_glyph_fn)(X11DRV_PDEVICE *, INT, INT, void *, XGlyphInfo *);
1909
1910             if(aa_type == AA_None)
1911                 sharp_glyph_fn = SharpGlyphMono;
1912             else
1913                 sharp_glyph_fn = SharpGlyphGray;
1914
1915             for(idx = 0; idx < count; idx++) {
1916                 sharp_glyph_fn(physDev,
1917                                physDev->dc_rect.left + x + offset.x,
1918                                physDev->dc_rect.top  + y + offset.y,
1919                                formatEntry->bitmaps[wstr[idx]],
1920                                &formatEntry->gis[wstr[idx]]);
1921                 if(lpDx)
1922                 {
1923                     if(flags & ETO_PDY)
1924                     {
1925                         offset.x += lpDx[idx * 2];
1926                         offset.y += lpDx[idx * 2 + 1];
1927                     }
1928                     else
1929                         offset.x += lpDx[idx];
1930                 }
1931                 else
1932                 {
1933                     offset.x += formatEntry->gis[wstr[idx]].xOff;
1934                     offset.y += formatEntry->gis[wstr[idx]].yOff;
1935                 }
1936             }
1937         } else {
1938             XImage *image;
1939             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
1940             RECT extents = {0, 0, 0, 0};
1941             POINT cur = {0, 0};
1942             int w = physDev->drawable_rect.right - physDev->drawable_rect.left;
1943             int h = physDev->drawable_rect.bottom - physDev->drawable_rect.top;
1944
1945             TRACE("drawable %dx%d\n", w, h);
1946
1947             for(idx = 0; idx < count; idx++) {
1948                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
1949                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
1950                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
1951                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
1952                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
1953                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
1954                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
1955                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
1956
1957                 if(lpDx)
1958                 {
1959                     if(flags & ETO_PDY)
1960                     {
1961                         cur.x += lpDx[idx * 2];
1962                         cur.y += lpDx[idx * 2 + 1];
1963                     }
1964                     else
1965                         cur.x += lpDx[idx];
1966                 }
1967                 else
1968                 {
1969                     cur.x += formatEntry->gis[wstr[idx]].xOff;
1970                     cur.y += formatEntry->gis[wstr[idx]].yOff;
1971                 }
1972             }
1973             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
1974                   extents.right, extents.bottom, physDev->dc_rect.left + x, physDev->dc_rect.top + y);
1975
1976             if(physDev->dc_rect.left + x + extents.left >= 0) {
1977                 image_x = physDev->dc_rect.left + x + extents.left;
1978                 image_off_x = 0;
1979             } else {
1980                 image_x = 0;
1981                 image_off_x = physDev->dc_rect.left + x + extents.left;
1982             }
1983             if(physDev->dc_rect.top + y + extents.top >= 0) {
1984                 image_y = physDev->dc_rect.top + y + extents.top;
1985                 image_off_y = 0;
1986             } else {
1987                 image_y = 0;
1988                 image_off_y = physDev->dc_rect.top + y + extents.top;
1989             }
1990             if(physDev->dc_rect.left + x + extents.right < w)
1991                 image_w = physDev->dc_rect.left + x + extents.right - image_x;
1992             else
1993                 image_w = w - image_x;
1994             if(physDev->dc_rect.top + y + extents.bottom < h)
1995                 image_h = physDev->dc_rect.top + y + extents.bottom - image_y;
1996             else
1997                 image_h = h - image_y;
1998
1999             if(image_w <= 0 || image_h <= 0) goto no_image;
2000
2001             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2002             image = XGetImage(gdi_display, physDev->drawable,
2003                               image_x, image_y, image_w, image_h,
2004                               AllPlanes, ZPixmap);
2005             X11DRV_check_error();
2006
2007             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2008                   gdi_display, (int)physDev->drawable, image_x, image_y,
2009                   image_w, image_h, AllPlanes, ZPixmap,
2010                   physDev->depth, image);
2011             if(!image) {
2012                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
2013                                            physDev->depth);
2014                 GC gc;
2015                 XGCValues gcv;
2016
2017                 gcv.graphics_exposures = False;
2018                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
2019                 XCopyArea(gdi_display, physDev->drawable, xpm, gc, image_x, image_y,
2020                           image_w, image_h, 0, 0);
2021                 XFreeGC(gdi_display, gc);
2022                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2023                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
2024                                   ZPixmap);
2025                 X11DRV_check_error();
2026                 XFreePixmap(gdi_display, xpm);
2027             }
2028             if(!image) goto no_image;
2029
2030             image->red_mask = visual->red_mask;
2031             image->green_mask = visual->green_mask;
2032             image->blue_mask = visual->blue_mask;
2033
2034             for(idx = 0; idx < count; idx++) {
2035                 SmoothGlyphGray(image,
2036                                 offset.x + image_off_x - extents.left,
2037                                 offset.y + image_off_y - extents.top,
2038                                 formatEntry->bitmaps[wstr[idx]],
2039                                 &formatEntry->gis[wstr[idx]],
2040                                 physDev->textPixel);
2041                 if(lpDx)
2042                 {
2043                     if(flags & ETO_PDY)
2044                     {
2045                         offset.x += lpDx[idx * 2];
2046                         offset.y += lpDx[idx * 2 + 1];
2047                     }
2048                     else
2049                         offset.x += lpDx[idx];
2050                 }
2051                 else
2052                 {
2053                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2054                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2055                 }
2056             }
2057             XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
2058                       image_x, image_y, image_w, image_h);
2059             XDestroyImage(image);
2060         }
2061     no_image:
2062         wine_tsx11_unlock();
2063     }
2064     LeaveCriticalSection(&xrender_cs);
2065
2066     if (flags & ETO_CLIPPED)
2067     {
2068         /* restore the device region */
2069         X11DRV_SetDeviceClipping( physDev, saved_region, 0 );
2070         DeleteObject( saved_region );
2071     }
2072
2073     retv = TRUE;
2074
2075 done_unlock:
2076     X11DRV_UnlockDIBSection( physDev, TRUE );
2077     return retv;
2078 }
2079
2080 /* Helper function for (stretched) blitting using xrender */
2081 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
2082                           int x_src, int y_src, int x_dst, int y_dst,
2083                           double xscale, double yscale, int width, int height )
2084 {
2085     int x_offset, y_offset;
2086
2087     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2088      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2089      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2090     if(xscale != 1.0 || yscale != 1.0)
2091     {
2092         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2093          * in the wrong quadrant of the x-y plane.
2094          */
2095         x_offset = (xscale < 0) ? -width : 0;
2096         y_offset = (yscale < 0) ? -height : 0;
2097         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2098     }
2099     else
2100     {
2101         x_offset = x_src;
2102         y_offset = y_src;
2103         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2104     }
2105     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
2106                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
2107 }
2108
2109 /* Helper function for (stretched) mono->color blitting using xrender */
2110 static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_pict,
2111                                int x_src, int y_src, double xscale, double yscale, int width, int height )
2112 {
2113     int x_offset, y_offset;
2114
2115     /* When doing a mono->color blit, 'src_pict' contains a 1x1 picture for tiling, the actual
2116      * source data is in mask_pict.  The 'src_pict' data effectively acts as an alpha channel to the
2117      * tile data. We need PictOpOver for correct rendering.
2118      * Note since the 'source data' is in the mask picture, we have to pass x_src / y_src using
2119      * mask_x / mask_y
2120      */
2121     if (xscale != 1.0 || yscale != 1.0)
2122     {
2123         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2124          * in the wrong quadrant of the x-y plane.
2125          */
2126         x_offset = (xscale < 0) ? -width : 0;
2127         y_offset = (yscale < 0) ? -height : 0;
2128         set_xrender_transformation(mask_pict, xscale, yscale, x_src, y_src);
2129     }
2130     else
2131     {
2132         x_offset = x_src;
2133         y_offset = y_src;
2134         set_xrender_transformation(mask_pict, 1, 1, 0, 0);
2135     }
2136     pXRenderComposite(gdi_display, PictOpOver, src_pict, mask_pict, dst_pict,
2137                       0, 0, x_offset, y_offset, 0, 0, width, height);
2138 }
2139
2140 /******************************************************************************
2141  * AlphaBlend
2142  */
2143 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2144                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2145 {
2146     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2147     struct xrender_info *src_info = get_xrender_info( devSrc );
2148     double xscale, yscale;
2149     BOOL use_repeat;
2150
2151     if(!X11DRV_XRender_Installed) {
2152         FIXME("Unable to AlphaBlend without Xrender\n");
2153         return FALSE;
2154     }
2155
2156     if (devSrc != devDst) X11DRV_LockDIBSection( devSrc, DIB_Status_GdiMod );
2157     X11DRV_LockDIBSection( devDst, DIB_Status_GdiMod );
2158
2159     dst_pict = get_xrender_picture( devDst );
2160
2161     use_repeat = use_source_repeat( devSrc );
2162     if (!use_repeat)
2163     {
2164         xscale = src->width / (double)dst->width;
2165         yscale = src->height / (double)dst->height;
2166     }
2167     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2168
2169     if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && src_info->format)
2170     {
2171         /* we need a source picture with no alpha */
2172         WXRFormat format = get_format_without_alpha( src_info->format->format );
2173         if (format != src_info->format->format)
2174         {
2175             XRenderPictureAttributes pa;
2176             const WineXRenderFormat *fmt = get_xrender_format( format );
2177
2178             wine_tsx11_lock();
2179             pa.subwindow_mode = IncludeInferiors;
2180             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2181             tmp_pict = pXRenderCreatePicture( gdi_display, devSrc->drawable, fmt->pict_format,
2182                                               CPSubwindowMode|CPRepeat, &pa );
2183             wine_tsx11_unlock();
2184             src_pict = tmp_pict;
2185         }
2186     }
2187
2188     if (!src_pict) src_pict = get_xrender_picture_source( devSrc, use_repeat );
2189
2190     EnterCriticalSection( &xrender_cs );
2191     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2192
2193     wine_tsx11_lock();
2194     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2195                   devSrc->dc_rect.left + src->visrect.left, devSrc->dc_rect.top + src->visrect.top,
2196                   devDst->dc_rect.left + dst->visrect.left, devDst->dc_rect.top + dst->visrect.top,
2197                   xscale, yscale,
2198                   dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top );
2199     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2200     wine_tsx11_unlock();
2201
2202     LeaveCriticalSection( &xrender_cs );
2203     if (devSrc != devDst) X11DRV_UnlockDIBSection( devSrc, FALSE );
2204     X11DRV_UnlockDIBSection( devDst, TRUE );
2205     return TRUE;
2206 }
2207
2208
2209 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2210 {
2211     /* At depths >1, the depth of physBitmap and physDev might not be the same e.g. the physbitmap might be a 16-bit DIB while the physdev uses 24-bit */
2212     int depth = physBitmap->pixmap_depth == 1 ? 1 : physDev->depth;
2213     const WineXRenderFormat *src_format = get_xrender_format_from_color_shifts(physBitmap->pixmap_depth, &physBitmap->pixmap_color_shifts);
2214     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
2215
2216     wine_tsx11_lock();
2217     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, depth);
2218
2219     /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2220     if( (physBitmap->pixmap_depth == 1) || (!X11DRV_XRender_Installed && physDev->depth == physBitmap->pixmap_depth) ||
2221         (src_format->format == dst_format->format) )
2222     {
2223         XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2224                    get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2225     }
2226     else /* We need depth conversion */
2227     {
2228         Picture src_pict, dst_pict;
2229         XRenderPictureAttributes pa;
2230         pa.subwindow_mode = IncludeInferiors;
2231         pa.repeat = RepeatNone;
2232
2233         src_pict = pXRenderCreatePicture(gdi_display, physBitmap->pixmap, src_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2234         dst_pict = pXRenderCreatePicture(gdi_display, physDev->brush.pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2235
2236         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, width, height);
2237         pXRenderFreePicture(gdi_display, src_pict);
2238         pXRenderFreePicture(gdi_display, dst_pict);
2239     }
2240     wine_tsx11_unlock();
2241 }
2242
2243 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2244                                       Pixmap pixmap, GC gc,
2245                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2246 {
2247     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2248     int width = dst->visrect.right - dst->visrect.left;
2249     int height = dst->visrect.bottom - dst->visrect.top;
2250     int x_src = physDevSrc->dc_rect.left + src->visrect.left;
2251     int y_src = physDevSrc->dc_rect.top + src->visrect.top;
2252     struct xrender_info *src_info = get_xrender_info(physDevSrc);
2253     const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDevDst->depth, physDevDst->color_shifts);
2254     Picture src_pict=0, dst_pict=0, mask_pict=0;
2255     BOOL use_repeat;
2256     double xscale, yscale;
2257
2258     XRenderPictureAttributes pa;
2259     pa.subwindow_mode = IncludeInferiors;
2260     pa.repeat = RepeatNone;
2261
2262     TRACE("src depth=%d widthSrc=%d heightSrc=%d xSrc=%d ySrc=%d\n",
2263           physDevSrc->depth, src->width, src->height, x_src, y_src);
2264     TRACE("dst depth=%d widthDst=%d heightDst=%d\n", physDevDst->depth, dst->width, dst->height);
2265
2266     if(!X11DRV_XRender_Installed)
2267     {
2268         TRACE("Not using XRender since it is not available or disabled\n");
2269         return FALSE;
2270     }
2271
2272     /* XRender can't handle palettes, so abort */
2273     if(X11DRV_PALETTE_XPixelToPalette)
2274         return FALSE;
2275
2276     /* XRender is of no use in this case */
2277     if((physDevDst->depth == 1) && (physDevSrc->depth > 1))
2278         return FALSE;
2279
2280     /* Just use traditional X copy when the formats match and we don't need stretching */
2281     if((src_info->format->format == dst_format->format) && !stretch)
2282     {
2283         TRACE("Source and destination depth match and no stretching needed falling back to XCopyArea\n");
2284         wine_tsx11_lock();
2285         XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc, x_src, y_src, width, height, 0, 0);
2286         wine_tsx11_unlock();
2287         return TRUE;
2288     }
2289
2290     use_repeat = use_source_repeat( physDevSrc );
2291     if (!use_repeat)
2292     {
2293         xscale = src->width / (double)dst->width;
2294         yscale = src->height / (double)dst->height;
2295     }
2296     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2297
2298     /* mono -> color */
2299     if(physDevSrc->depth == 1 && physDevDst->depth > 1)
2300     {
2301         XRenderColor col;
2302         get_xrender_color(dst_format, physDevDst->textPixel, &col);
2303
2304         /* We use the source drawable as a mask */
2305         mask_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2306
2307         /* Use backgroundPixel as the foreground color */
2308         EnterCriticalSection( &xrender_cs );
2309         src_pict = get_tile_pict(dst_format, physDevDst->backgroundPixel);
2310
2311         /* Create a destination picture and fill it with textPixel color as the background color */
2312         wine_tsx11_lock();
2313         dst_pict = pXRenderCreatePicture(gdi_display, pixmap, dst_format->pict_format, CPSubwindowMode|CPRepeat, &pa);
2314         pXRenderFillRectangle(gdi_display, PictOpSrc, dst_pict, &col, 0, 0, width, height);
2315
2316         xrender_mono_blit(src_pict, mask_pict, dst_pict, x_src, y_src, xscale, yscale, width, height);
2317
2318         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2319         wine_tsx11_unlock();
2320         LeaveCriticalSection( &xrender_cs );
2321     }
2322     else /* color -> color (can be at different depths) or mono -> mono */
2323     {
2324         if (physDevDst->depth == 32 && physDevSrc->depth < 32) mask_pict = get_no_alpha_mask();
2325         src_pict = get_xrender_picture_source( physDevSrc, use_repeat );
2326
2327         wine_tsx11_lock();
2328         dst_pict = pXRenderCreatePicture(gdi_display,
2329                                           pixmap, dst_format->pict_format,
2330                                           CPSubwindowMode|CPRepeat, &pa);
2331
2332         xrender_blit(PictOpSrc, src_pict, mask_pict, dst_pict,
2333                      x_src, y_src, 0, 0, xscale, yscale, width, height);
2334
2335         if(dst_pict) pXRenderFreePicture(gdi_display, dst_pict);
2336         wine_tsx11_unlock();
2337     }
2338     return TRUE;
2339 }
2340
2341 #else /* SONAME_LIBXRENDER */
2342
2343 void X11DRV_XRender_Init(void)
2344 {
2345     TRACE("XRender support not compiled in.\n");
2346     return;
2347 }
2348
2349 void X11DRV_XRender_Finalize(void)
2350 {
2351 }
2352
2353 BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
2354 {
2355   assert(0);
2356   return FALSE;
2357 }
2358
2359 void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
2360 {
2361   assert(0);
2362   return;
2363 }
2364
2365 void X11DRV_XRender_SetDeviceClipping(X11DRV_PDEVICE *physDev, const RGNDATA *data)
2366 {
2367     assert(0);
2368     return;
2369 }
2370
2371 BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
2372                                 const RECT *lprect, LPCWSTR wstr, UINT count,
2373                                 const INT *lpDx )
2374 {
2375   assert(0);
2376   return FALSE;
2377 }
2378
2379 void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
2380 {
2381   assert(0);
2382   return;
2383 }
2384
2385 BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
2386                          struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2387 {
2388   FIXME("not supported - XRENDER headers were missing at compile time\n");
2389   return FALSE;
2390 }
2391
2392 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2393 {
2394     wine_tsx11_lock();
2395     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, physBitmap->pixmap_depth);
2396
2397     XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2398                get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2399     wine_tsx11_unlock();
2400 }
2401
2402 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2403 {
2404     return FALSE;
2405 }
2406
2407 BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
2408                                       Pixmap pixmap, GC gc,
2409                                       const struct bitblt_coords *src, const struct bitblt_coords *dst )
2410 {
2411     return FALSE;
2412 }
2413 #endif /* SONAME_LIBXRENDER */