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