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