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