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