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