dinput: Fix printing NULL strings.
[wine] / dlls / winex11.drv / xrender.c
1 /*
2  * Functions to use the XRender extension
3  *
4  * Copyright 2001, 2002 Huw D M Davies for CodeWeavers
5  * Copyright 2009 Roderick Colenbrander
6  *
7  * Some parts also:
8  * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "x11drv.h"
35 #include "winternl.h"
36 #include "wine/library.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
39
40 int using_client_side_fonts = FALSE;
41
42 WINE_DEFAULT_DEBUG_CHANNEL(xrender);
43
44 #ifdef SONAME_LIBXRENDER
45
46 static BOOL X11DRV_XRender_Installed = FALSE;
47
48 #include <X11/Xlib.h>
49 #include <X11/extensions/Xrender.h>
50
51 #ifndef RepeatNone  /* added in 0.10 */
52 #define RepeatNone    0
53 #define RepeatNormal  1
54 #define RepeatPad     2
55 #define RepeatReflect 3
56 #endif
57
58 enum wxr_format
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_B8G8R8A8,
70   WXR_FORMAT_X8R8G8B8,
71   WXR_FORMAT_B8G8R8X8,
72   WXR_NB_FORMATS,
73   WXR_INVALID_FORMAT = WXR_NB_FORMATS
74 };
75
76 typedef struct wine_xrender_format_template
77 {
78     unsigned int depth;
79     unsigned int alpha;
80     unsigned int alphaMask;
81     unsigned int red;
82     unsigned int redMask;
83     unsigned int green;
84     unsigned int greenMask;
85     unsigned int blue;
86     unsigned int blueMask;
87 } WineXRenderFormatTemplate;
88
89 static const WineXRenderFormatTemplate wxr_formats_template[WXR_NB_FORMATS] =
90 {
91     /* Format               depth   alpha   mask    red     mask    green   mask    blue    mask*/
92 /* WXR_FORMAT_MONO     */ { 1,      0,      0x01,   0,      0,      0,      0,      0,      0       },
93 /* WXR_FORMAT_GRAY     */ { 8,      0,      0xff,   0,      0,      0,      0,      0,      0       },
94 /* WXR_FORMAT_X1R5G5B5 */ { 16,     0,      0,      10,     0x1f,   5,      0x1f,   0,      0x1f    },
95 /* WXR_FORMAT_X1B5G5R5 */ { 16,     0,      0,      0,      0x1f,   5,      0x1f,   10,     0x1f    },
96 /* WXR_FORMAT_R5G6B5   */ { 16,     0,      0,      11,     0x1f,   5,      0x3f,   0,      0x1f    },
97 /* WXR_FORMAT_B5G6R5   */ { 16,     0,      0,      0,      0x1f,   5,      0x3f,   11,     0x1f    },
98 /* WXR_FORMAT_R8G8B8   */ { 24,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
99 /* WXR_FORMAT_B8G8R8   */ { 24,     0,      0,      0,      0xff,   8,      0xff,   16,     0xff    },
100 /* WXR_FORMAT_A8R8G8B8 */ { 32,     24,     0xff,   16,     0xff,   8,      0xff,   0,      0xff    },
101 /* WXR_FORMAT_B8G8R8A8 */ { 32,     0,      0xff,   8,      0xff,   16,     0xff,   24,     0xff    },
102 /* WXR_FORMAT_X8R8G8B8 */ { 32,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
103 /* WXR_FORMAT_B8G8R8X8 */ { 32,     0,      0,      8,      0xff,   16,     0xff,   24,     0xff    },
104 };
105
106 static enum wxr_format default_format;
107 static XRenderPictFormat *pict_formats[WXR_NB_FORMATS + 1 /* invalid format */];
108
109 typedef struct
110 {
111     LOGFONTW lf;
112     XFORM    xform;
113     SIZE     devsize;  /* size in device coords */
114     DWORD    hash;
115 } LFANDSIZE;
116
117 #define INITIAL_REALIZED_BUF_SIZE 128
118
119 typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
120
121 typedef struct
122 {
123     GlyphSet glyphset;
124     XRenderPictFormat *font_format;
125     int nrealized;
126     BOOL *realized;
127     void **bitmaps;
128     XGlyphInfo *gis;
129 } gsCacheEntryFormat;
130
131 typedef struct
132 {
133     LFANDSIZE lfsz;
134     AA_Type aa_default;
135     gsCacheEntryFormat * format[AA_MAXVALUE];
136     INT count;
137     INT next;
138 } gsCacheEntry;
139
140 struct xrender_physdev
141 {
142     struct gdi_physdev dev;
143     X11DRV_PDEVICE    *x11dev;
144     enum wxr_format    format;
145     int                cache_index;
146     Picture            pict;
147     Picture            pict_src;
148     XRenderPictFormat *pict_format;
149 };
150
151 static inline struct xrender_physdev *get_xrender_dev( PHYSDEV dev )
152 {
153     return (struct xrender_physdev *)dev;
154 }
155
156 static const struct gdi_dc_funcs xrender_funcs;
157
158 static gsCacheEntry *glyphsetCache = NULL;
159 static DWORD glyphsetCacheSize = 0;
160 static INT lastfree = -1;
161 static INT mru = -1;
162
163 #define INIT_CACHE_SIZE 10
164
165 static int antialias = 1;
166
167 static void *xrender_handle;
168
169 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
170 MAKE_FUNCPTR(XRenderAddGlyphs)
171 MAKE_FUNCPTR(XRenderComposite)
172 MAKE_FUNCPTR(XRenderCompositeString8)
173 MAKE_FUNCPTR(XRenderCompositeString16)
174 MAKE_FUNCPTR(XRenderCompositeString32)
175 MAKE_FUNCPTR(XRenderCompositeText16)
176 MAKE_FUNCPTR(XRenderCreateGlyphSet)
177 MAKE_FUNCPTR(XRenderCreatePicture)
178 MAKE_FUNCPTR(XRenderFillRectangle)
179 MAKE_FUNCPTR(XRenderFindFormat)
180 MAKE_FUNCPTR(XRenderFindVisualFormat)
181 MAKE_FUNCPTR(XRenderFreeGlyphSet)
182 MAKE_FUNCPTR(XRenderFreePicture)
183 MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
184 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
185 MAKE_FUNCPTR(XRenderSetPictureTransform)
186 #endif
187 MAKE_FUNCPTR(XRenderQueryExtension)
188
189 #ifdef SONAME_LIBFONTCONFIG
190 #include <fontconfig/fontconfig.h>
191 MAKE_FUNCPTR(FcConfigSubstitute)
192 MAKE_FUNCPTR(FcDefaultSubstitute)
193 MAKE_FUNCPTR(FcFontMatch)
194 MAKE_FUNCPTR(FcInit)
195 MAKE_FUNCPTR(FcPatternCreate)
196 MAKE_FUNCPTR(FcPatternDestroy)
197 MAKE_FUNCPTR(FcPatternAddInteger)
198 MAKE_FUNCPTR(FcPatternAddString)
199 MAKE_FUNCPTR(FcPatternGetBool)
200 MAKE_FUNCPTR(FcPatternGetInteger)
201 MAKE_FUNCPTR(FcPatternGetString)
202 static void *fontconfig_handle;
203 static BOOL fontconfig_installed;
204 #endif
205
206 #undef MAKE_FUNCPTR
207
208 static CRITICAL_SECTION xrender_cs;
209 static CRITICAL_SECTION_DEBUG critsect_debug =
210 {
211     0, 0, &xrender_cs,
212     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
213       0, 0, { (DWORD_PTR)(__FILE__ ": xrender_cs") }
214 };
215 static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
216
217 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
218           ( ( (ULONG)_x4 << 24 ) |     \
219             ( (ULONG)_x3 << 16 ) |     \
220             ( (ULONG)_x2 <<  8 ) |     \
221               (ULONG)_x1         )
222
223 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
224
225 #define GASP_GRIDFIT 0x01
226 #define GASP_DOGRAY  0x02
227
228 #ifdef WORDS_BIGENDIAN
229 #define get_be_word(x) (x)
230 #define NATIVE_BYTE_ORDER MSBFirst
231 #else
232 #define get_be_word(x) RtlUshortByteSwap(x)
233 #define NATIVE_BYTE_ORDER LSBFirst
234 #endif
235
236 static enum wxr_format get_format_without_alpha( enum wxr_format format )
237 {
238     switch (format)
239     {
240     case WXR_FORMAT_A8R8G8B8: return WXR_FORMAT_X8R8G8B8;
241     case WXR_FORMAT_B8G8R8A8: return WXR_FORMAT_B8G8R8X8;
242     default: return format;
243     }
244 }
245
246 static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
247 {
248     templ->id = 0;
249     templ->type = PictTypeDirect;
250     templ->depth = fmt->depth;
251     templ->direct.alpha = fmt->alpha;
252     templ->direct.alphaMask = fmt->alphaMask;
253     templ->direct.red = fmt->red;
254     templ->direct.redMask = fmt->redMask;
255     templ->direct.green = fmt->green;
256     templ->direct.greenMask = fmt->greenMask;
257     templ->direct.blue = fmt->blue;
258     templ->direct.blueMask = fmt->blueMask;
259     templ->colormap = 0;
260
261     *mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
262
263     return TRUE;
264 }
265
266 static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
267 {
268     if(fmt->depth != screen_depth)
269         return FALSE;
270     if( (fmt->redMask << fmt->red) != visual->red_mask)
271         return FALSE;
272     if( (fmt->greenMask << fmt->green) != visual->green_mask)
273         return FALSE;
274     if( (fmt->blueMask << fmt->blue) != visual->blue_mask)
275         return FALSE;
276
277     /* We never select a default ARGB visual */
278     if(fmt->alphaMask)
279         return FALSE;
280
281     return TRUE;
282 }
283
284 static int load_xrender_formats(void)
285 {
286     int count = 0;
287     unsigned int i;
288
289     for (i = 0; i < WXR_NB_FORMATS; i++)
290     {
291         XRenderPictFormat templ;
292
293         if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
294         {
295             wine_tsx11_lock();
296             pict_formats[i] = pXRenderFindVisualFormat(gdi_display, visual);
297             if (!pict_formats[i])
298             {
299                 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
300                 if (visual->class == DirectColor)
301                 {
302                     XVisualInfo info;
303                     if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
304                                           screen_depth, TrueColor, &info ))
305                     {
306                         pict_formats[i] = pXRenderFindVisualFormat(gdi_display, info.visual);
307                         if (pict_formats[i]) visual = info.visual;
308                     }
309                 }
310             }
311             wine_tsx11_unlock();
312             if (pict_formats[i]) default_format = i;
313         }
314         else
315         {
316             unsigned long mask = 0;
317             get_xrender_template(&wxr_formats_template[i], &templ, &mask);
318
319             wine_tsx11_lock();
320             pict_formats[i] = pXRenderFindFormat(gdi_display, mask, &templ, 0);
321             wine_tsx11_unlock();
322         }
323         if (pict_formats[i])
324         {
325             count++;
326             TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats[i]->id, i);
327         }
328     }
329     return count;
330 }
331
332 /***********************************************************************
333  *   X11DRV_XRender_Init
334  *
335  * Let's see if our XServer has the extension available
336  *
337  */
338 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
339 {
340     int event_base, i;
341
342     if (client_side_with_render &&
343         (xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0)))
344     {
345
346 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
347 LOAD_FUNCPTR(XRenderAddGlyphs)
348 LOAD_FUNCPTR(XRenderComposite)
349 LOAD_FUNCPTR(XRenderCompositeString8)
350 LOAD_FUNCPTR(XRenderCompositeString16)
351 LOAD_FUNCPTR(XRenderCompositeString32)
352 LOAD_FUNCPTR(XRenderCompositeText16)
353 LOAD_FUNCPTR(XRenderCreateGlyphSet)
354 LOAD_FUNCPTR(XRenderCreatePicture)
355 LOAD_FUNCPTR(XRenderFillRectangle)
356 LOAD_FUNCPTR(XRenderFindFormat)
357 LOAD_FUNCPTR(XRenderFindVisualFormat)
358 LOAD_FUNCPTR(XRenderFreeGlyphSet)
359 LOAD_FUNCPTR(XRenderFreePicture)
360 LOAD_FUNCPTR(XRenderSetPictureClipRectangles)
361 LOAD_FUNCPTR(XRenderQueryExtension)
362 #undef LOAD_FUNCPTR
363 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
364 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0);
365 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform)
366 #undef LOAD_OPTIONAL_FUNCPTR
367 #endif
368
369         wine_tsx11_lock();
370         X11DRV_XRender_Installed = pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base);
371         wine_tsx11_unlock();
372         if(X11DRV_XRender_Installed) {
373             TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
374             if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
375             {
376                 wine_tsx11_unlock();
377                 WINE_MESSAGE(
378                     "Wine has detected that you probably have a buggy version\n"
379                     "of libXrender.so .  Because of this client side font rendering\n"
380                     "will be disabled.  Please upgrade this library.\n");
381                 X11DRV_XRender_Installed = FALSE;
382                 return NULL;
383             }
384
385             if (!visual->red_mask || !visual->green_mask || !visual->blue_mask) {
386                 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
387                 X11DRV_XRender_Installed = FALSE;
388             }
389         }
390     }
391
392 #ifdef SONAME_LIBFONTCONFIG
393     if ((fontconfig_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0)))
394     {
395 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(fontconfig_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
396         LOAD_FUNCPTR(FcConfigSubstitute);
397         LOAD_FUNCPTR(FcDefaultSubstitute);
398         LOAD_FUNCPTR(FcFontMatch);
399         LOAD_FUNCPTR(FcInit);
400         LOAD_FUNCPTR(FcPatternCreate);
401         LOAD_FUNCPTR(FcPatternDestroy);
402         LOAD_FUNCPTR(FcPatternAddInteger);
403         LOAD_FUNCPTR(FcPatternAddString);
404         LOAD_FUNCPTR(FcPatternGetBool);
405         LOAD_FUNCPTR(FcPatternGetInteger);
406         LOAD_FUNCPTR(FcPatternGetString);
407 #undef LOAD_FUNCPTR
408         fontconfig_installed = pFcInit();
409     }
410     else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG "\n" );
411 #endif
412
413 sym_not_found:
414     if(X11DRV_XRender_Installed || client_side_with_core)
415     {
416         glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
417                                   sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
418
419         glyphsetCacheSize = INIT_CACHE_SIZE;
420         lastfree = 0;
421         for(i = 0; i < INIT_CACHE_SIZE; i++) {
422           glyphsetCache[i].next = i + 1;
423           glyphsetCache[i].count = -1;
424         }
425         glyphsetCache[i-1].next = -1;
426         using_client_side_fonts = 1;
427
428         if(!X11DRV_XRender_Installed) {
429             TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
430             if(screen_depth <= 8 || !client_side_antialias_with_core)
431                 antialias = 0;
432         } else {
433             if(screen_depth <= 8 || !client_side_antialias_with_render)
434                 antialias = 0;
435         }
436         return &xrender_funcs;
437     }
438     TRACE("Using X11 core fonts\n");
439     return NULL;
440 }
441
442 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
443 static void get_xrender_color( XRenderPictFormat *pf, int src_color, XRenderColor *dst_color )
444 {
445     if(pf->direct.redMask)
446         dst_color->red = ((src_color >> pf->direct.red) & pf->direct.redMask) * 65535/pf->direct.redMask;
447     else
448        dst_color->red = 0;
449
450     if(pf->direct.greenMask)
451         dst_color->green = ((src_color >> pf->direct.green) & pf->direct.greenMask) * 65535/pf->direct.greenMask;
452     else
453         dst_color->green = 0;
454
455     if(pf->direct.blueMask)
456         dst_color->blue = ((src_color >> pf->direct.blue) & pf->direct.blueMask) * 65535/pf->direct.blueMask;
457     else
458         dst_color->blue = 0;
459
460     dst_color->alpha = 0xffff;
461 }
462
463 static enum wxr_format get_xrender_format_from_color_shifts(int depth, ColorShifts *shifts)
464 {
465     int redMask, greenMask, blueMask;
466     unsigned int i;
467
468     if (depth == 1) return WXR_FORMAT_MONO;
469
470     /* physDevs of a depth <=8, don't have color_shifts set and XRender can't handle those except for 1-bit */
471     if (!shifts) return default_format;
472
473     redMask   = shifts->physicalRed.max << shifts->physicalRed.shift;
474     greenMask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
475     blueMask  = shifts->physicalBlue.max << shifts->physicalBlue.shift;
476
477     /* Try to locate a format which matches the specification of the dibsection. */
478     for(i = 0; i < WXR_NB_FORMATS; i++)
479     {
480         if( depth     == wxr_formats_template[i].depth &&
481             redMask   == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
482             greenMask == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
483             blueMask  == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue) )
484             return i;
485     }
486
487     /* This should not happen because when we reach 'shifts' must have been set and we only allows shifts which are backed by X */
488     ERR("No XRender format found!\n");
489     return WXR_INVALID_FORMAT;
490 }
491
492 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
493 static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
494 {
495 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
496     XTransform xform = {{
497         { XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(xoffset) },
498         { XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(yoffset) },
499         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
500     }};
501
502     pXRenderSetPictureTransform(gdi_display, src_pict, &xform);
503 #endif
504 }
505
506 /* check if we can use repeating instead of scaling for the specified source DC */
507 static BOOL use_source_repeat( struct xrender_physdev *dev )
508 {
509     return (dev->x11dev->bitmap &&
510             dev->x11dev->drawable_rect.right - dev->x11dev->drawable_rect.left == 1 &&
511             dev->x11dev->drawable_rect.bottom - dev->x11dev->drawable_rect.top == 1);
512 }
513
514 static Picture get_xrender_picture( struct xrender_physdev *dev )
515 {
516     if (!dev->pict && dev->pict_format)
517     {
518         XRenderPictureAttributes pa;
519         RGNDATA *clip = X11DRV_GetRegionData( dev->x11dev->region, 0 );
520
521         wine_tsx11_lock();
522         pa.subwindow_mode = IncludeInferiors;
523         dev->pict = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
524                                            dev->pict_format, CPSubwindowMode, &pa );
525         if (dev->pict && clip)
526             pXRenderSetPictureClipRectangles( gdi_display, dev->pict,
527                                               dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top,
528                                               (XRectangle *)clip->Buffer, clip->rdh.nCount );
529         wine_tsx11_unlock();
530         TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
531                dev->pict, dev->dev.hdc, dev->x11dev->drawable );
532         HeapFree( GetProcessHeap(), 0, clip );
533     }
534
535     return dev->pict;
536 }
537
538 static Picture get_xrender_picture_source( struct xrender_physdev *dev, BOOL repeat )
539 {
540     if (!dev->pict_src && dev->pict_format)
541     {
542         XRenderPictureAttributes pa;
543
544         wine_tsx11_lock();
545         pa.subwindow_mode = IncludeInferiors;
546         pa.repeat = repeat ? RepeatNormal : RepeatNone;
547         dev->pict_src = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
548                                                dev->pict_format, CPSubwindowMode|CPRepeat, &pa );
549         wine_tsx11_unlock();
550
551         TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
552               dev->pict_src, dev->dev.hdc, dev->x11dev->drawable, pa.repeat);
553     }
554
555     return dev->pict_src;
556 }
557
558 static void free_xrender_picture( struct xrender_physdev *dev )
559 {
560     if (dev->pict || dev->pict_src)
561     {
562         wine_tsx11_lock();
563         XFlush( gdi_display );
564         if (dev->pict)
565         {
566             TRACE("freeing pict = %lx dc = %p\n", dev->pict, dev->dev.hdc);
567             pXRenderFreePicture(gdi_display, dev->pict);
568             dev->pict = 0;
569         }
570         if(dev->pict_src)
571         {
572             TRACE("freeing pict = %lx dc = %p\n", dev->pict_src, dev->dev.hdc);
573             pXRenderFreePicture(gdi_display, dev->pict_src);
574             dev->pict_src = 0;
575         }
576         wine_tsx11_unlock();
577     }
578     dev->pict_format = NULL;
579 }
580
581 static void update_xrender_drawable( struct xrender_physdev *dev )
582 {
583     free_xrender_picture( dev );
584     dev->format = get_xrender_format_from_color_shifts( dev->x11dev->depth, dev->x11dev->color_shifts );
585     dev->pict_format = pict_formats[dev->format];
586 }
587
588 /* return a mask picture used to force alpha to 0 */
589 static Picture get_no_alpha_mask(void)
590 {
591     static Pixmap pixmap;
592     static Picture pict;
593
594     wine_tsx11_lock();
595     if (!pict)
596     {
597         XRenderPictureAttributes pa;
598         XRenderColor col;
599
600         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
601         pa.repeat = RepeatNormal;
602         pa.component_alpha = True;
603         pict = pXRenderCreatePicture( gdi_display, pixmap, pict_formats[WXR_FORMAT_A8R8G8B8],
604                                       CPRepeat|CPComponentAlpha, &pa );
605         col.red = col.green = col.blue = 0xffff;
606         col.alpha = 0;
607         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
608     }
609     wine_tsx11_unlock();
610     return pict;
611 }
612
613 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
614 {
615   if(p1->hash != p2->hash) return TRUE;
616   if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE;
617   if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE;
618   if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
619   return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName);
620 }
621
622 #if 0
623 static void walk_cache(void)
624 {
625   int i;
626
627   EnterCriticalSection(&xrender_cs);
628   for(i=mru; i >= 0; i = glyphsetCache[i].next)
629     TRACE("item %d\n", i);
630   LeaveCriticalSection(&xrender_cs);
631 }
632 #endif
633
634 static int LookupEntry(LFANDSIZE *plfsz)
635 {
636   int i, prev_i = -1;
637
638   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
639     TRACE("%d\n", i);
640     if(glyphsetCache[i].count == -1) break; /* reached free list so stop */
641
642     if(!fontcmp(&glyphsetCache[i].lfsz, plfsz)) {
643       glyphsetCache[i].count++;
644       if(prev_i >= 0) {
645         glyphsetCache[prev_i].next = glyphsetCache[i].next;
646         glyphsetCache[i].next = mru;
647         mru = i;
648       }
649       TRACE("found font in cache %d\n", i);
650       return i;
651     }
652     prev_i = i;
653   }
654   TRACE("font not in cache\n");
655   return -1;
656 }
657
658 static void FreeEntry(int entry)
659 {
660     int i, format;
661   
662     for(format = 0; format < AA_MAXVALUE; format++) {
663         gsCacheEntryFormat * formatEntry;
664
665         if( !glyphsetCache[entry].format[format] )
666             continue;
667
668         formatEntry = glyphsetCache[entry].format[format];
669
670         if(formatEntry->glyphset) {
671             wine_tsx11_lock();
672             pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
673             wine_tsx11_unlock();
674             formatEntry->glyphset = 0;
675         }
676         if(formatEntry->nrealized) {
677             HeapFree(GetProcessHeap(), 0, formatEntry->realized);
678             formatEntry->realized = NULL;
679             if(formatEntry->bitmaps) {
680                 for(i = 0; i < formatEntry->nrealized; i++)
681                     HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps[i]);
682                 HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps);
683                 formatEntry->bitmaps = NULL;
684             }
685             HeapFree(GetProcessHeap(), 0, formatEntry->gis);
686             formatEntry->gis = NULL;
687             formatEntry->nrealized = 0;
688         }
689
690         HeapFree(GetProcessHeap(), 0, formatEntry);
691         glyphsetCache[entry].format[format] = NULL;
692     }
693 }
694
695 static int AllocEntry(void)
696 {
697   int best = -1, prev_best = -1, i, prev_i = -1;
698
699   if(lastfree >= 0) {
700     assert(glyphsetCache[lastfree].count == -1);
701     glyphsetCache[lastfree].count = 1;
702     best = lastfree;
703     lastfree = glyphsetCache[lastfree].next;
704     assert(best != mru);
705     glyphsetCache[best].next = mru;
706     mru = best;
707
708     TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
709     return mru;
710   }
711
712   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
713     if(glyphsetCache[i].count == 0) {
714       best = i;
715       prev_best = prev_i;
716     }
717     prev_i = i;
718   }
719
720   if(best >= 0) {
721     TRACE("freeing unused glyphset at cache %d\n", best);
722     FreeEntry(best);
723     glyphsetCache[best].count = 1;
724     if(prev_best >= 0) {
725       glyphsetCache[prev_best].next = glyphsetCache[best].next;
726       glyphsetCache[best].next = mru;
727       mru = best;
728     } else {
729       assert(mru == best);
730     }
731     return mru;
732   }
733
734   TRACE("Growing cache\n");
735   
736   if (glyphsetCache)
737     glyphsetCache = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
738                               glyphsetCache,
739                               (glyphsetCacheSize + INIT_CACHE_SIZE)
740                               * sizeof(*glyphsetCache));
741   else
742     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
743                               (glyphsetCacheSize + INIT_CACHE_SIZE)
744                               * sizeof(*glyphsetCache));
745
746   for(best = i = glyphsetCacheSize; i < glyphsetCacheSize + INIT_CACHE_SIZE;
747       i++) {
748     glyphsetCache[i].next = i + 1;
749     glyphsetCache[i].count = -1;
750   }
751   glyphsetCache[i-1].next = -1;
752   glyphsetCacheSize += INIT_CACHE_SIZE;
753
754   lastfree = glyphsetCache[best].next;
755   glyphsetCache[best].count = 1;
756   glyphsetCache[best].next = mru;
757   mru = best;
758   TRACE("new free cache slot at %d\n", mru);
759   return mru;
760 }
761
762 static BOOL get_gasp_flags(HDC hdc, WORD *flags)
763 {
764     DWORD size;
765     WORD *gasp, *buffer;
766     WORD num_recs;
767     DWORD ppem;
768     TEXTMETRICW tm;
769
770     *flags = 0;
771
772     size = GetFontData(hdc, MS_GASP_TAG,  0, NULL, 0);
773     if(size == GDI_ERROR)
774         return FALSE;
775
776     gasp = buffer = HeapAlloc(GetProcessHeap(), 0, size);
777     GetFontData(hdc, MS_GASP_TAG,  0, gasp, size);
778
779     GetTextMetricsW(hdc, &tm);
780     ppem = abs(X11DRV_YWStoDS(hdc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading));
781
782     gasp++;
783     num_recs = get_be_word(*gasp);
784     gasp++;
785     while(num_recs--)
786     {
787         *flags = get_be_word(*(gasp + 1));
788         if(ppem <= get_be_word(*gasp))
789             break;
790         gasp += 2;
791     }
792     TRACE("got flags %04x for ppem %d\n", *flags, ppem);
793
794     HeapFree(GetProcessHeap(), 0, buffer);
795     return TRUE;
796 }
797
798 static AA_Type get_antialias_type( HDC hdc, BOOL subpixel, BOOL hinter )
799 {
800     AA_Type ret;
801     WORD flags;
802     UINT font_smoothing_type, font_smoothing_orientation;
803
804     if (X11DRV_XRender_Installed && subpixel &&
805         SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE, 0, &font_smoothing_type, 0) &&
806         font_smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
807     {
808         if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION, 0,
809                                     &font_smoothing_orientation, 0) &&
810              font_smoothing_orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
811         {
812             ret = AA_BGR;
813         }
814         else
815             ret = AA_RGB;
816         /*FIXME
817           If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
818           But, Wine's subpixel rendering can support the portrait mode.
819          */
820     }
821     else if (!hinter || !get_gasp_flags(hdc, &flags) || flags & GASP_DOGRAY)
822         ret = AA_Grey;
823     else
824         ret = AA_None;
825
826     return ret;
827 }
828
829 static int GetCacheEntry( HDC hdc, LFANDSIZE *plfsz )
830 {
831     int ret;
832     int format;
833     gsCacheEntry *entry;
834     static int hinter = -1;
835     static int subpixel = -1;
836     BOOL font_smoothing;
837
838     if((ret = LookupEntry(plfsz)) != -1) return ret;
839
840     ret = AllocEntry();
841     entry = glyphsetCache + ret;
842     entry->lfsz = *plfsz;
843     for( format = 0; format < AA_MAXVALUE; format++ ) {
844         assert( !entry->format[format] );
845     }
846
847     if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY)
848     {
849         if(hinter == -1 || subpixel == -1)
850         {
851             RASTERIZER_STATUS status;
852             GetRasterizerCaps(&status, sizeof(status));
853             hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
854             subpixel = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
855         }
856
857         switch (plfsz->lf.lfQuality)
858         {
859             case ANTIALIASED_QUALITY:
860                 entry->aa_default = get_antialias_type( hdc, FALSE, hinter );
861                 return ret;  /* ignore further configuration */
862             case CLEARTYPE_QUALITY:
863             case CLEARTYPE_NATURAL_QUALITY:
864                 entry->aa_default = get_antialias_type( hdc, subpixel, hinter );
865                 break;
866             case DEFAULT_QUALITY:
867             case DRAFT_QUALITY:
868             case PROOF_QUALITY:
869             default:
870                 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0) &&
871                      font_smoothing)
872                 {
873                     entry->aa_default = get_antialias_type( hdc, subpixel, hinter );
874                 }
875                 else
876                     entry->aa_default = AA_None;
877                 break;
878         }
879
880         font_smoothing = TRUE;  /* default to enabled */
881 #ifdef SONAME_LIBFONTCONFIG
882         if (fontconfig_installed)
883         {
884             FcPattern *match, *pattern = pFcPatternCreate();
885             FcResult result;
886             char family[LF_FACESIZE * 4];
887
888             WideCharToMultiByte( CP_UTF8, 0, plfsz->lf.lfFaceName, -1, family, sizeof(family), NULL, NULL );
889             pFcPatternAddString( pattern, FC_FAMILY, (FcChar8 *)family );
890             if (plfsz->lf.lfWeight != FW_DONTCARE)
891             {
892                 int weight;
893                 switch (plfsz->lf.lfWeight)
894                 {
895                 case FW_THIN:       weight = FC_WEIGHT_THIN; break;
896                 case FW_EXTRALIGHT: weight = FC_WEIGHT_EXTRALIGHT; break;
897                 case FW_LIGHT:      weight = FC_WEIGHT_LIGHT; break;
898                 case FW_NORMAL:     weight = FC_WEIGHT_NORMAL; break;
899                 case FW_MEDIUM:     weight = FC_WEIGHT_MEDIUM; break;
900                 case FW_SEMIBOLD:   weight = FC_WEIGHT_SEMIBOLD; break;
901                 case FW_BOLD:       weight = FC_WEIGHT_BOLD; break;
902                 case FW_EXTRABOLD:  weight = FC_WEIGHT_EXTRABOLD; break;
903                 case FW_HEAVY:      weight = FC_WEIGHT_HEAVY; break;
904                 default:            weight = (plfsz->lf.lfWeight - 80) / 4; break;
905                 }
906                 pFcPatternAddInteger( pattern, FC_WEIGHT, weight );
907             }
908             pFcPatternAddInteger( pattern, FC_SLANT, plfsz->lf.lfItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
909             pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
910             pFcDefaultSubstitute( pattern );
911             if ((match = pFcFontMatch( NULL, pattern, &result )))
912             {
913                 int rgba;
914                 FcBool antialias;
915
916                 if (pFcPatternGetBool( match, FC_ANTIALIAS, 0, &antialias ) != FcResultMatch)
917                     antialias = TRUE;
918                 if (pFcPatternGetInteger( match, FC_RGBA, 0, &rgba ) == FcResultMatch)
919                 {
920                     FcChar8 *file;
921                     if (pFcPatternGetString( match, FC_FILE, 0, &file ) != FcResultMatch) file = NULL;
922
923                     TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
924                            rgba, antialias, debugstr_w(plfsz->lf.lfFaceName), debugstr_a((char *)file) );
925
926                     switch (rgba)
927                     {
928                     case FC_RGBA_RGB:  entry->aa_default = AA_RGB; break;
929                     case FC_RGBA_BGR:  entry->aa_default = AA_BGR; break;
930                     case FC_RGBA_VRGB: entry->aa_default = AA_VRGB; break;
931                     case FC_RGBA_VBGR: entry->aa_default = AA_VBGR; break;
932                     case FC_RGBA_NONE: entry->aa_default = AA_Grey; break;
933                     }
934                 }
935                 if (!antialias) font_smoothing = FALSE;
936                 pFcPatternDestroy( match );
937             }
938             pFcPatternDestroy( pattern );
939         }
940 #endif  /* SONAME_LIBFONTCONFIG */
941
942         /* now check Xft resources */
943         {
944             char *value;
945             BOOL antialias = TRUE;
946
947             wine_tsx11_lock();
948             if ((value = XGetDefault( gdi_display, "Xft", "antialias" )))
949             {
950                 if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
951                     value[0] == '0' || !strcasecmp( value, "off" ))
952                     antialias = FALSE;
953             }
954             if ((value = XGetDefault( gdi_display, "Xft", "rgba" )))
955             {
956                 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value, antialias );
957                 if (!strcmp( value, "rgb" )) entry->aa_default = AA_RGB;
958                 else if (!strcmp( value, "bgr" )) entry->aa_default = AA_BGR;
959                 else if (!strcmp( value, "vrgb" )) entry->aa_default = AA_VRGB;
960                 else if (!strcmp( value, "vbgr" )) entry->aa_default = AA_VBGR;
961                 else if (!strcmp( value, "none" )) entry->aa_default = AA_Grey;
962             }
963             wine_tsx11_unlock();
964             if (!antialias) font_smoothing = FALSE;
965         }
966
967         if (!font_smoothing) entry->aa_default = AA_None;
968
969         /* we can't support subpixel without xrender */
970         if (!X11DRV_XRender_Installed && entry->aa_default > AA_Grey) entry->aa_default = AA_Grey;
971     }
972     else
973         entry->aa_default = AA_None;
974
975     return ret;
976 }
977
978 static void dec_ref_cache(int index)
979 {
980     assert(index >= 0);
981     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
982     assert(glyphsetCache[index].count > 0);
983     glyphsetCache[index].count--;
984 }
985
986 static void lfsz_calc_hash(LFANDSIZE *plfsz)
987 {
988   DWORD hash = 0, *ptr, two_chars;
989   WORD *pwc;
990   int i;
991
992   hash ^= plfsz->devsize.cx;
993   hash ^= plfsz->devsize.cy;
994   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
995     hash ^= *ptr;
996   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
997     hash ^= *ptr;
998   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
999     two_chars = *ptr;
1000     pwc = (WCHAR *)&two_chars;
1001     if(!*pwc) break;
1002     *pwc = toupperW(*pwc);
1003     pwc++;
1004     *pwc = toupperW(*pwc);
1005     hash ^= two_chars;
1006     if(!*pwc) break;
1007   }
1008   plfsz->hash = hash;
1009   return;
1010 }
1011
1012 /***********************************************************************
1013  *   X11DRV_XRender_Finalize
1014  */
1015 void X11DRV_XRender_Finalize(void)
1016 {
1017     int i;
1018
1019     EnterCriticalSection(&xrender_cs);
1020     for(i = mru; i >= 0; i = glyphsetCache[i].next)
1021         FreeEntry(i);
1022     LeaveCriticalSection(&xrender_cs);
1023 }
1024
1025 /**********************************************************************
1026  *           xrenderdrv_SelectFont
1027  */
1028 static HFONT xrenderdrv_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
1029 {
1030     struct xrender_physdev *physdev = get_xrender_dev( dev );
1031     LFANDSIZE lfsz;
1032
1033     if (!GetObjectW( hfont, sizeof(lfsz.lf), &lfsz.lf )) return HGDI_ERROR;
1034
1035     if (!gdiFont)
1036     {
1037         dev = GET_NEXT_PHYSDEV( dev, pSelectFont );
1038         return dev->funcs->pSelectFont( dev, hfont, gdiFont );
1039     }
1040
1041     TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1042           lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
1043           lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
1044     lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
1045     lfsz.devsize.cx = X11DRV_XWStoDS( dev->hdc, lfsz.lf.lfWidth );
1046     lfsz.devsize.cy = X11DRV_YWStoDS( dev->hdc, lfsz.lf.lfHeight );
1047
1048     GetTransform( dev->hdc, 0x204, &lfsz.xform );
1049     TRACE("font transform %f %f %f %f\n", lfsz.xform.eM11, lfsz.xform.eM12,
1050           lfsz.xform.eM21, lfsz.xform.eM22);
1051
1052     /* Not used fields, would break hashing */
1053     lfsz.xform.eDx = lfsz.xform.eDy = 0;
1054
1055     lfsz_calc_hash(&lfsz);
1056
1057     EnterCriticalSection(&xrender_cs);
1058     if (physdev->cache_index != -1)
1059         dec_ref_cache( physdev->cache_index );
1060     physdev->cache_index = GetCacheEntry( dev->hdc, &lfsz );
1061     LeaveCriticalSection(&xrender_cs);
1062     physdev->x11dev->has_gdi_font = TRUE;
1063     return 0;
1064 }
1065
1066 static void update_xrender_clipping( struct xrender_physdev *dev, const RGNDATA *data )
1067 {
1068     if (dev->pict)
1069     {
1070         wine_tsx11_lock();
1071         pXRenderSetPictureClipRectangles( gdi_display, dev->pict,
1072                                           dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top,
1073                                           (XRectangle *)data->Buffer, data->rdh.nCount );
1074         wine_tsx11_unlock();
1075     }
1076 }
1077
1078 static RGNDATA *add_xrender_clipping_region( struct xrender_physdev *dev, HRGN rgn )
1079 {
1080     RGNDATA *ret, *data;
1081     HRGN clip;
1082
1083     if (!(ret = X11DRV_GetRegionData( dev->x11dev->region, 0 ))) return NULL;
1084     if (!(clip = CreateRectRgn( 0, 0, 0, 0 )))
1085     {
1086         HeapFree( GetProcessHeap(), 0, ret );
1087         return NULL;
1088     }
1089     CombineRgn( clip, dev->x11dev->region, rgn, RGN_AND );
1090     if ((data = X11DRV_GetRegionData( clip, 0 )))
1091     {
1092         update_xrender_clipping( dev, data );
1093         HeapFree( GetProcessHeap(), 0, data );
1094     }
1095     DeleteObject( clip );
1096     return ret;
1097 }
1098
1099 static void restore_xrender_clipping_region( struct xrender_physdev *dev, RGNDATA *data )
1100 {
1101     if (!data) return;
1102     update_xrender_clipping( dev, data );
1103     HeapFree( GetProcessHeap(), 0, data );
1104 }
1105
1106 static BOOL create_xrender_dc( PHYSDEV *pdev )
1107 {
1108     X11DRV_PDEVICE *x11dev = get_x11drv_dev( *pdev );
1109     struct xrender_physdev *physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) );
1110
1111     if (!physdev) return FALSE;
1112     physdev->x11dev = x11dev;
1113     physdev->cache_index = -1;
1114     physdev->format = get_xrender_format_from_color_shifts( x11dev->depth, x11dev->color_shifts );
1115     physdev->pict_format = pict_formats[physdev->format];
1116     push_dc_driver( pdev, &physdev->dev, &xrender_funcs );
1117     return TRUE;
1118 }
1119
1120 /**********************************************************************
1121  *           xrenderdrv_CreateDC
1122  */
1123 static BOOL xrenderdrv_CreateDC( PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
1124                                  LPCWSTR output, const DEVMODEW* initData )
1125 {
1126     return create_xrender_dc( pdev );
1127 }
1128
1129 /**********************************************************************
1130  *           xrenderdrv_CreateCompatibleDC
1131  */
1132 static BOOL xrenderdrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
1133 {
1134     if (orig)  /* chain to x11drv first */
1135     {
1136         orig = GET_NEXT_PHYSDEV( orig, pCreateCompatibleDC );
1137         if (!orig->funcs->pCreateCompatibleDC( orig, pdev )) return FALSE;
1138     }
1139     /* otherwise we have been called by x11drv */
1140
1141     return create_xrender_dc( pdev );
1142 }
1143
1144 /**********************************************************************
1145  *           xrenderdrv_DeleteDC
1146  */
1147 static BOOL xrenderdrv_DeleteDC( PHYSDEV dev )
1148 {
1149     struct xrender_physdev *physdev = get_xrender_dev( dev );
1150
1151     free_xrender_picture( physdev );
1152
1153     EnterCriticalSection( &xrender_cs );
1154     if (physdev->cache_index != -1) dec_ref_cache( physdev->cache_index );
1155     LeaveCriticalSection( &xrender_cs );
1156
1157     HeapFree( GetProcessHeap(), 0, physdev );
1158     return TRUE;
1159 }
1160
1161 /**********************************************************************
1162  *           xrenderdrv_ExtEscape
1163  */
1164 static INT xrenderdrv_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data,
1165                                  INT out_count, LPVOID out_data )
1166 {
1167     struct xrender_physdev *physdev = get_xrender_dev( dev );
1168
1169     dev = GET_NEXT_PHYSDEV( dev, pExtEscape );
1170
1171     if (escape == X11DRV_ESCAPE && in_data && in_count >= sizeof(enum x11drv_escape_codes))
1172     {
1173         if (*(const enum x11drv_escape_codes *)in_data == X11DRV_SET_DRAWABLE)
1174         {
1175             BOOL ret = dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1176             if (ret) update_xrender_drawable( physdev );
1177             return ret;
1178         }
1179     }
1180     return dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1181 }
1182
1183 /****************************************************************************
1184  *        xrenderdrv_CreateBitmap
1185  */
1186 static BOOL xrenderdrv_CreateBitmap( PHYSDEV dev, HBITMAP hbitmap )
1187 {
1188     XRenderPictFormat *pict_format = NULL;
1189     ColorShifts shifts;
1190     BITMAP bitmap;
1191
1192     if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return FALSE;
1193
1194     if (bitmap.bmPlanes == 1 && bitmap.bmBitsPixel == screen_bpp)
1195     {
1196         switch (bitmap.bmBitsPixel)
1197         {
1198         case 16: pict_format = pict_formats[WXR_FORMAT_R5G6B5]; break;
1199         case 24: pict_format = pict_formats[WXR_FORMAT_R8G8B8]; break;
1200         case 32: pict_format = pict_formats[WXR_FORMAT_A8R8G8B8]; break;
1201         }
1202     }
1203
1204     if (pict_format)
1205     {
1206         X11DRV_PALETTE_ComputeColorShifts( &shifts,
1207                                            pict_format->direct.redMask << pict_format->direct.red,
1208                                            pict_format->direct.greenMask << pict_format->direct.green,
1209                                            pict_format->direct.blueMask << pict_format->direct.blue );
1210         return X11DRV_create_phys_bitmap( hbitmap, &bitmap, pict_format->depth, TRUE, &shifts );
1211     }
1212
1213     dev = GET_NEXT_PHYSDEV( dev, pCreateBitmap );
1214     return dev->funcs->pCreateBitmap( dev, hbitmap );
1215 }
1216
1217 /****************************************************************************
1218  *        xrenderdrv_DeleteBitmap
1219  */
1220 static BOOL xrenderdrv_DeleteBitmap( HBITMAP hbitmap )
1221 {
1222     return X11DRV_DeleteBitmap( hbitmap );
1223 }
1224
1225 /***********************************************************************
1226  *           xrenderdrv_SelectBitmap
1227  */
1228 static HBITMAP xrenderdrv_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
1229 {
1230     HBITMAP ret;
1231     struct xrender_physdev *physdev = get_xrender_dev( dev );
1232
1233     dev = GET_NEXT_PHYSDEV( dev, pSelectBitmap );
1234     ret = dev->funcs->pSelectBitmap( dev, hbitmap );
1235     if (ret) update_xrender_drawable( physdev );
1236     return ret;
1237 }
1238
1239 /***********************************************************************
1240  *           xrenderdrv_GetImage
1241  */
1242 static DWORD xrenderdrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1243                                   struct gdi_image_bits *bits, struct bitblt_coords *src )
1244 {
1245     if (hbitmap) return X11DRV_GetImage( dev, hbitmap, info, bits, src );
1246     dev = GET_NEXT_PHYSDEV( dev, pGetImage );
1247     return dev->funcs->pGetImage( dev, hbitmap, info, bits, src );
1248 }
1249
1250 /***********************************************************************
1251  *           xrenderdrv_PutImage
1252  */
1253 static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1254                                   const struct gdi_image_bits *bits, struct bitblt_coords *src,
1255                                   struct bitblt_coords *dst, DWORD rop )
1256 {
1257     if (hbitmap) return X11DRV_PutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
1258     dev = GET_NEXT_PHYSDEV( dev, pPutImage );
1259     return dev->funcs->pPutImage( dev, hbitmap, clip, info, bits, src, dst, rop );
1260 }
1261
1262 /***********************************************************************
1263  *           xrenderdrv_SetDeviceClipping
1264  */
1265 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev, HRGN vis_rgn, HRGN clip_rgn )
1266 {
1267     struct xrender_physdev *physdev = get_xrender_dev( dev );
1268     RGNDATA *data;
1269
1270     CombineRgn( physdev->x11dev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY );
1271
1272     if (!(data = X11DRV_GetRegionData( physdev->x11dev->region, 0 ))) return;
1273     update_x11_clipping( physdev->x11dev, data );
1274     update_xrender_clipping( physdev, data );
1275     HeapFree( GetProcessHeap(), 0, data );
1276 }
1277
1278
1279 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
1280 {
1281     XRenderPictFormat *pict_format;
1282     ColorShifts shifts;
1283     const DWORD *bitfields;
1284     static const DWORD bitfields_32[3] = {0xff0000, 0x00ff00, 0x0000ff};
1285     static const DWORD bitfields_16[3] = {0x7c00, 0x03e0, 0x001f};
1286
1287
1288     /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1289      * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1290      * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1291     if (!X11DRV_XRender_Installed || bits_pixel <= 8)
1292         return FALSE;
1293
1294     if(dib->dsBmih.biCompression == BI_BITFIELDS)
1295         bitfields = dib->dsBitfields;
1296     else if(bits_pixel == 24 || bits_pixel == 32)
1297         bitfields = bitfields_32;
1298     else
1299         bitfields = bitfields_16;
1300
1301     X11DRV_PALETTE_ComputeColorShifts(&shifts, bitfields[0], bitfields[1], bitfields[2]);
1302     pict_format = pict_formats[get_xrender_format_from_color_shifts(dib->dsBm.bmBitsPixel, &shifts)];
1303
1304     /* Common formats should be in our picture format table. */
1305     if (!pict_format)
1306     {
1307         TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1308               dib->dsBm.bmBitsPixel, bitfields[0], bitfields[1], bitfields[2]);
1309         return FALSE;
1310     }
1311
1312     physBitmap->pixmap_depth = pict_format->depth;
1313     physBitmap->trueColor = TRUE;
1314     physBitmap->pixmap_color_shifts = shifts;
1315     return TRUE;
1316 }
1317
1318 /************************************************************************
1319  *   UploadGlyph
1320  *
1321  * Helper to ExtTextOut.  Must be called inside xrender_cs
1322  */
1323 static void UploadGlyph(struct xrender_physdev *physDev, int glyph, AA_Type format)
1324 {
1325     unsigned int buflen;
1326     char *buf;
1327     Glyph gid;
1328     GLYPHMETRICS gm;
1329     XGlyphInfo gi;
1330     gsCacheEntry *entry = glyphsetCache + physDev->cache_index;
1331     gsCacheEntryFormat *formatEntry;
1332     UINT ggo_format = GGO_GLYPH_INDEX;
1333     enum wxr_format wxr_format;
1334     static const char zero[4];
1335     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1336
1337     switch(format) {
1338     case AA_Grey:
1339         ggo_format |= WINE_GGO_GRAY16_BITMAP;
1340         break;
1341     case AA_RGB:
1342         ggo_format |= WINE_GGO_HRGB_BITMAP;
1343         break;
1344     case AA_BGR:
1345         ggo_format |= WINE_GGO_HBGR_BITMAP;
1346         break;
1347     case AA_VRGB:
1348         ggo_format |= WINE_GGO_VRGB_BITMAP;
1349         break;
1350     case AA_VBGR:
1351         ggo_format |= WINE_GGO_VBGR_BITMAP;
1352         break;
1353
1354     default:
1355         ERR("aa = %d - not implemented\n", format);
1356     case AA_None:
1357         ggo_format |= GGO_BITMAP;
1358         break;
1359     }
1360
1361     buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1362     if(buflen == GDI_ERROR) {
1363         if(format != AA_None) {
1364             format = AA_None;
1365             entry->aa_default = AA_None;
1366             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1367             buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1368         }
1369         if(buflen == GDI_ERROR) {
1370             WARN("GetGlyphOutlineW failed using default glyph\n");
1371             buflen = GetGlyphOutlineW(physDev->dev.hdc, 0, ggo_format, &gm, 0, NULL, &identity);
1372             if(buflen == GDI_ERROR) {
1373                 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1374                 buflen = GetGlyphOutlineW(physDev->dev.hdc, 0x20, ggo_format, &gm, 0, NULL, &identity);
1375                 if(buflen == GDI_ERROR) {
1376                     ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1377                     return;
1378                 }
1379             }
1380         }
1381         TRACE("Turning off antialiasing for this monochrome font\n");
1382     }
1383
1384     /* If there is nothing for the current type, we create the entry. */
1385     if( !entry->format[format] ) {
1386         entry->format[format] = HeapAlloc(GetProcessHeap(),
1387                                           HEAP_ZERO_MEMORY,
1388                                           sizeof(gsCacheEntryFormat));
1389     }
1390     formatEntry = entry->format[format];
1391
1392     if(formatEntry->nrealized <= glyph) {
1393         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1394
1395         if (formatEntry->realized)
1396             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1397                                       HEAP_ZERO_MEMORY,
1398                                       formatEntry->realized,
1399                                       formatEntry->nrealized * sizeof(BOOL));
1400         else
1401             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1402                                       HEAP_ZERO_MEMORY,
1403                                       formatEntry->nrealized * sizeof(BOOL));
1404
1405         if(!X11DRV_XRender_Installed) {
1406           if (formatEntry->bitmaps)
1407             formatEntry->bitmaps = HeapReAlloc(GetProcessHeap(),
1408                                       HEAP_ZERO_MEMORY,
1409                                       formatEntry->bitmaps,
1410                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1411           else
1412             formatEntry->bitmaps = HeapAlloc(GetProcessHeap(),
1413                                       HEAP_ZERO_MEMORY,
1414                                       formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
1415         }
1416         if (formatEntry->gis)
1417             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1418                                    HEAP_ZERO_MEMORY,
1419                                    formatEntry->gis,
1420                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1421         else
1422             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1423                                    HEAP_ZERO_MEMORY,
1424                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1425     }
1426
1427
1428     if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
1429         switch(format) {
1430             case AA_Grey:
1431                 wxr_format = WXR_FORMAT_GRAY;
1432                 break;
1433
1434             case AA_RGB:
1435             case AA_BGR:
1436             case AA_VRGB:
1437             case AA_VBGR:
1438                 wxr_format = WXR_FORMAT_A8R8G8B8;
1439                 break;
1440
1441             default:
1442                 ERR("aa = %d - not implemented\n", format);
1443             case AA_None:
1444                 wxr_format = WXR_FORMAT_MONO;
1445                 break;
1446         }
1447
1448         wine_tsx11_lock();
1449         formatEntry->font_format = pict_formats[wxr_format];
1450         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format);
1451         wine_tsx11_unlock();
1452     }
1453
1454
1455     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1456     GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1457     formatEntry->realized[glyph] = TRUE;
1458
1459     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1460           buflen,
1461           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1462           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1463
1464     gi.width = gm.gmBlackBoxX;
1465     gi.height = gm.gmBlackBoxY;
1466     gi.x = -gm.gmptGlyphOrigin.x;
1467     gi.y = gm.gmptGlyphOrigin.y;
1468     gi.xOff = gm.gmCellIncX;
1469     gi.yOff = gm.gmCellIncY;
1470
1471     if(TRACE_ON(xrender)) {
1472         int pitch, i, j;
1473         char output[300];
1474         unsigned char *line;
1475
1476         if(format == AA_None) {
1477             pitch = ((gi.width + 31) / 32) * 4;
1478             for(i = 0; i < gi.height; i++) {
1479                 line = (unsigned char*) buf + i * pitch;
1480                 output[0] = '\0';
1481                 for(j = 0; j < pitch * 8; j++) {
1482                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1483                 }
1484                 TRACE("%s\n", output);
1485             }
1486         } else {
1487             static const char blks[] = " .:;!o*#";
1488             char str[2];
1489
1490             str[1] = '\0';
1491             pitch = ((gi.width + 3) / 4) * 4;
1492             for(i = 0; i < gi.height; i++) {
1493                 line = (unsigned char*) buf + i * pitch;
1494                 output[0] = '\0';
1495                 for(j = 0; j < pitch; j++) {
1496                     str[0] = blks[line[j] >> 5];
1497                     strcat(output, str);
1498                 }
1499                 TRACE("%s\n", output);
1500             }
1501         }
1502     }
1503
1504
1505     if(formatEntry->glyphset) {
1506         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1507             unsigned char *byte = (unsigned char*) buf, c;
1508             int i = buflen;
1509
1510             while(i--) {
1511                 c = *byte;
1512
1513                 /* magic to flip bit order */
1514                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1515                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1516                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1517
1518                 *byte++ = c;
1519             }
1520         }
1521         else if ( format != AA_Grey &&
1522                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1523         {
1524             unsigned int i, *data = (unsigned int *)buf;
1525             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1526         }
1527         gid = glyph;
1528
1529         /*
1530           XRenderCompositeText seems to ignore 0x0 glyphs when
1531           AA_None, which means we lose the advance width of glyphs
1532           like the space.  We'll pretend that such glyphs are 1x1
1533           bitmaps.
1534         */
1535
1536         if(buflen == 0)
1537             gi.width = gi.height = 1;
1538
1539         wine_tsx11_lock();
1540         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1541                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1542         wine_tsx11_unlock();
1543         HeapFree(GetProcessHeap(), 0, buf);
1544     } else {
1545         formatEntry->bitmaps[glyph] = buf;
1546     }
1547
1548     formatEntry->gis[glyph] = gi;
1549 }
1550
1551 static void SharpGlyphMono(struct xrender_physdev *physDev, INT x, INT y,
1552                             void *bitmap, XGlyphInfo *gi)
1553 {
1554     unsigned char   *srcLine = bitmap, *src;
1555     unsigned char   bits, bitsMask;
1556     int             width = gi->width;
1557     int             stride = ((width + 31) & ~31) >> 3;
1558     int             height = gi->height;
1559     int             w;
1560     int             xspan, lenspan;
1561
1562     TRACE("%d, %d\n", x, y);
1563     x -= gi->x;
1564     y -= gi->y;
1565     while (height--)
1566     {
1567         src = srcLine;
1568         srcLine += stride;
1569         w = width;
1570         
1571         bitsMask = 0x80;    /* FreeType is always MSB first */
1572         bits = *src++;
1573         
1574         xspan = x;
1575         while (w)
1576         {
1577             if (bits & bitsMask)
1578             {
1579                 lenspan = 0;
1580                 do
1581                 {
1582                     lenspan++;
1583                     if (lenspan == w)
1584                         break;
1585                     bitsMask = bitsMask >> 1;
1586                     if (!bitsMask)
1587                     {
1588                         bits = *src++;
1589                         bitsMask = 0x80;
1590                     }
1591                 } while (bits & bitsMask);
1592                 XFillRectangle (gdi_display, physDev->x11dev->drawable,
1593                                 physDev->x11dev->gc, xspan, y, lenspan, 1);
1594                 xspan += lenspan;
1595                 w -= lenspan;
1596             }
1597             else
1598             {
1599                 do
1600                 {
1601                     w--;
1602                     xspan++;
1603                     if (!w)
1604                         break;
1605                     bitsMask = bitsMask >> 1;
1606                     if (!bitsMask)
1607                     {
1608                         bits = *src++;
1609                         bitsMask = 0x80;
1610                     }
1611                 } while (!(bits & bitsMask));
1612             }
1613         }
1614         y++;
1615     }
1616 }
1617
1618 static void SharpGlyphGray(struct xrender_physdev *physDev, INT x, INT y,
1619                             void *bitmap, XGlyphInfo *gi)
1620 {
1621     unsigned char   *srcLine = bitmap, *src, bits;
1622     int             width = gi->width;
1623     int             stride = ((width + 3) & ~3);
1624     int             height = gi->height;
1625     int             w;
1626     int             xspan, lenspan;
1627
1628     x -= gi->x;
1629     y -= gi->y;
1630     while (height--)
1631     {
1632         src = srcLine;
1633         srcLine += stride;
1634         w = width;
1635         
1636         bits = *src++;
1637         xspan = x;
1638         while (w)
1639         {
1640             if (bits >= 0x80)
1641             {
1642                 lenspan = 0;
1643                 do
1644                 {
1645                     lenspan++;
1646                     if (lenspan == w)
1647                         break;
1648                     bits = *src++;
1649                 } while (bits >= 0x80);
1650                 XFillRectangle (gdi_display, physDev->x11dev->drawable,
1651                                 physDev->x11dev->gc, xspan, y, lenspan, 1);
1652                 xspan += lenspan;
1653                 w -= lenspan;
1654             }
1655             else
1656             {
1657                 do
1658                 {
1659                     w--;
1660                     xspan++;
1661                     if (!w)
1662                         break;
1663                     bits = *src++;
1664                 } while (bits < 0x80);
1665             }
1666         }
1667         y++;
1668     }
1669 }
1670
1671
1672 static void ExamineBitfield (DWORD mask, int *shift, int *len)
1673 {
1674     int s, l;
1675
1676     s = 0;
1677     while ((mask & 1) == 0)
1678     {
1679         mask >>= 1;
1680         s++;
1681     }
1682     l = 0;
1683     while ((mask & 1) == 1)
1684     {
1685         mask >>= 1;
1686         l++;
1687     }
1688     *shift = s;
1689     *len = l;
1690 }
1691
1692 static DWORD GetField (DWORD pixel, int shift, int len)
1693 {
1694     pixel = pixel & (((1 << (len)) - 1) << shift);
1695     pixel = pixel << (32 - (shift + len)) >> 24;
1696     while (len < 8)
1697     {
1698         pixel |= (pixel >> len);
1699         len <<= 1;
1700     }
1701     return pixel;
1702 }
1703
1704
1705 static DWORD PutField (DWORD pixel, int shift, int len)
1706 {
1707     shift = shift - (8 - len);
1708     if (len <= 8)
1709         pixel &= (((1 << len) - 1) << (8 - len));
1710     if (shift < 0)
1711         pixel >>= -shift;
1712     else
1713         pixel <<= shift;
1714     return pixel;
1715 }
1716
1717 static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInfo *gi,
1718                             int color)
1719 {
1720     int             r_shift, r_len;
1721     int             g_shift, g_len;
1722     int             b_shift, b_len;
1723     BYTE            *maskLine, *mask, m;
1724     int             maskStride;
1725     DWORD           pixel;
1726     int             width, height;
1727     int             w, tx;
1728     BYTE            src_r, src_g, src_b;
1729
1730     x -= gi->x;
1731     y -= gi->y;
1732     width = gi->width;
1733     height = gi->height;
1734
1735     maskLine = bitmap;
1736     maskStride = (width + 3) & ~3;
1737
1738     ExamineBitfield (image->red_mask, &r_shift, &r_len);
1739     ExamineBitfield (image->green_mask, &g_shift, &g_len);
1740     ExamineBitfield (image->blue_mask, &b_shift, &b_len);
1741
1742     src_r = GetField(color, r_shift, r_len);
1743     src_g = GetField(color, g_shift, g_len);
1744     src_b = GetField(color, b_shift, b_len);
1745     
1746     for(; height--; y++)
1747     {
1748         mask = maskLine;
1749         maskLine += maskStride;
1750         w = width;
1751         tx = x;
1752
1753         if(y < 0) continue;
1754         if(y >= image->height) break;
1755
1756         for(; w--; tx++)
1757         {
1758             if(tx >= image->width) break;
1759
1760             m = *mask++;
1761             if(tx < 0) continue;
1762
1763             if (m == 0xff)
1764                 XPutPixel (image, tx, y, color);
1765             else if (m)
1766             {
1767                 BYTE r, g, b;
1768
1769                 pixel = XGetPixel (image, tx, y);
1770
1771                 r = GetField(pixel, r_shift, r_len);
1772                 r = ((BYTE)~m * (WORD)r + (BYTE)m * (WORD)src_r) >> 8;
1773                 g = GetField(pixel, g_shift, g_len);
1774                 g = ((BYTE)~m * (WORD)g + (BYTE)m * (WORD)src_g) >> 8;
1775                 b = GetField(pixel, b_shift, b_len);
1776                 b = ((BYTE)~m * (WORD)b + (BYTE)m * (WORD)src_b) >> 8;
1777
1778                 pixel = (PutField (r, r_shift, r_len) |
1779                          PutField (g, g_shift, g_len) |
1780                          PutField (b, b_shift, b_len));
1781                 XPutPixel (image, tx, y, pixel);
1782             }
1783         }
1784     }
1785 }
1786
1787 /*************************************************************
1788  *                 get_tile_pict
1789  *
1790  * Returns an appropriate Picture for tiling the text colour.
1791  * Call and use result within the xrender_cs
1792  */
1793 static Picture get_tile_pict( enum wxr_format wxr_format, const XRenderColor *color)
1794 {
1795     static struct
1796     {
1797         Pixmap xpm;
1798         Picture pict;
1799         XRenderColor current_color;
1800     } tiles[WXR_NB_FORMATS], *tile;
1801
1802     tile = &tiles[wxr_format];
1803
1804     if(!tile->xpm)
1805     {
1806         XRenderPictureAttributes pa;
1807         XRenderPictFormat *pict_format = pict_formats[wxr_format];
1808
1809         wine_tsx11_lock();
1810         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, pict_format->depth);
1811
1812         pa.repeat = RepeatNormal;
1813         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, pict_format, CPRepeat, &pa);
1814         wine_tsx11_unlock();
1815
1816         /* init current_color to something different from text_pixel */
1817         tile->current_color = *color;
1818         tile->current_color.red ^= 0xffff;
1819
1820         if (wxr_format == WXR_FORMAT_MONO)
1821         {
1822             /* for a 1bpp bitmap we always need a 1 in the tile */
1823             XRenderColor col;
1824             col.red = col.green = col.blue = 0;
1825             col.alpha = 0xffff;
1826             wine_tsx11_lock();
1827             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1828             wine_tsx11_unlock();
1829         }
1830     }
1831
1832     if (memcmp( color, &tile->current_color, sizeof(*color) ) && wxr_format != WXR_FORMAT_MONO)
1833     {
1834         wine_tsx11_lock();
1835         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, color, 0, 0, 1, 1);
1836         wine_tsx11_unlock();
1837         tile->current_color = *color;
1838     }
1839     return tile->pict;
1840 }
1841
1842 /*************************************************************
1843  *                 get_mask_pict
1844  *
1845  * Returns an appropriate Picture for masking with the specified alpha.
1846  * Call and use result within the xrender_cs
1847  */
1848 static Picture get_mask_pict( int alpha )
1849 {
1850     static Pixmap pixmap;
1851     static Picture pict;
1852     static int current_alpha;
1853
1854     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1855
1856     if (!pixmap)
1857     {
1858         XRenderPictureAttributes pa;
1859
1860         wine_tsx11_lock();
1861         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1862         pa.repeat = RepeatNormal;
1863         pict = pXRenderCreatePicture( gdi_display, pixmap,
1864                                       pict_formats[WXR_FORMAT_A8R8G8B8], CPRepeat, &pa );
1865         wine_tsx11_unlock();
1866         current_alpha = -1;
1867     }
1868
1869     if (alpha != current_alpha)
1870     {
1871         XRenderColor col;
1872         col.red = col.green = col.blue = 0;
1873         col.alpha = current_alpha = alpha;
1874         wine_tsx11_lock();
1875         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1876         wine_tsx11_unlock();
1877     }
1878     return pict;
1879 }
1880
1881 static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
1882 {
1883     return 1;
1884 }
1885
1886 /********************************************************************
1887  *                   is_dib_with_colortable
1888  *
1889  * Return TRUE if physdev is backed by a dibsection with <= 8 bits per pixel
1890  */
1891 static inline BOOL is_dib_with_colortable( X11DRV_PDEVICE *physDev )
1892 {
1893     DIBSECTION dib;
1894
1895     if( physDev->bitmap && GetObjectW( physDev->bitmap->hbitmap, sizeof(dib), &dib ) == sizeof(dib) &&
1896         dib.dsBmih.biBitCount <= 8 )
1897         return TRUE;
1898
1899     return FALSE;
1900 }
1901
1902 /***********************************************************************
1903  *           xrenderdrv_ExtTextOut
1904  */
1905 BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
1906                             const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx )
1907 {
1908     struct xrender_physdev *physdev = get_xrender_dev( dev );
1909     XGCValues xgcval;
1910     gsCacheEntry *entry;
1911     gsCacheEntryFormat *formatEntry;
1912     BOOL retv = FALSE;
1913     int textPixel, backgroundPixel;
1914     RGNDATA *saved_region = NULL;
1915     BOOL disable_antialias = FALSE;
1916     AA_Type aa_type = AA_None;
1917     unsigned int idx;
1918     Picture tile_pict = 0;
1919
1920     if (!physdev->x11dev->has_gdi_font)
1921     {
1922         dev = GET_NEXT_PHYSDEV( dev, pExtTextOut );
1923         return dev->funcs->pExtTextOut( dev, x, y, flags, lprect, wstr, count, lpDx );
1924     }
1925
1926     if(is_dib_with_colortable( physdev->x11dev ))
1927     {
1928         TRACE("Disabling antialiasing\n");
1929         disable_antialias = TRUE;
1930     }
1931
1932     xgcval.function = GXcopy;
1933     xgcval.background = physdev->x11dev->backgroundPixel;
1934     xgcval.fill_style = FillSolid;
1935     wine_tsx11_lock();
1936     XChangeGC( gdi_display, physdev->x11dev->gc, GCFunction | GCBackground | GCFillStyle, &xgcval );
1937     wine_tsx11_unlock();
1938
1939     X11DRV_LockDIBSection( physdev->x11dev, DIB_Status_GdiMod );
1940
1941     if(physdev->x11dev->depth == 1) {
1942         if((physdev->x11dev->textPixel & 0xffffff) == 0) {
1943             textPixel = 0;
1944             backgroundPixel = 1;
1945         } else {
1946             textPixel = 1;
1947             backgroundPixel = 0;
1948         }
1949     } else {
1950         textPixel = physdev->x11dev->textPixel;
1951         backgroundPixel = physdev->x11dev->backgroundPixel;
1952     }
1953
1954     if(flags & ETO_OPAQUE)
1955     {
1956         wine_tsx11_lock();
1957         XSetForeground( gdi_display, physdev->x11dev->gc, backgroundPixel );
1958         XFillRectangle( gdi_display, physdev->x11dev->drawable, physdev->x11dev->gc,
1959                         physdev->x11dev->dc_rect.left + lprect->left, physdev->x11dev->dc_rect.top + lprect->top,
1960                         lprect->right - lprect->left, lprect->bottom - lprect->top );
1961         wine_tsx11_unlock();
1962     }
1963
1964     if(count == 0)
1965     {
1966         retv = TRUE;
1967         goto done_unlock;
1968     }
1969
1970     EnterCriticalSection(&xrender_cs);
1971
1972     entry = glyphsetCache + physdev->cache_index;
1973     if( disable_antialias == FALSE )
1974         aa_type = entry->aa_default;
1975     formatEntry = entry->format[aa_type];
1976
1977     for(idx = 0; idx < count; idx++) {
1978         if( !formatEntry ) {
1979             UploadGlyph(physdev, wstr[idx], aa_type);
1980             /* re-evaluate antialias since aa_default may have changed */
1981             if( disable_antialias == FALSE )
1982                 aa_type = entry->aa_default;
1983             formatEntry = entry->format[aa_type];
1984         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1985             UploadGlyph(physdev, wstr[idx], aa_type);
1986         }
1987     }
1988     if (!formatEntry)
1989     {
1990         WARN("could not upload requested glyphs\n");
1991         LeaveCriticalSection(&xrender_cs);
1992         goto done_unlock;
1993     }
1994
1995     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1996           physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
1997
1998     if(X11DRV_XRender_Installed)
1999     {
2000         XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
2001         POINT offset = {0, 0};
2002         POINT desired, current;
2003         int render_op = PictOpOver;
2004         Picture pict = get_xrender_picture( physdev );
2005         XRenderColor col;
2006
2007         /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
2008            So we pass zeros to the function and move to our starting position using the first
2009            element of the elts array. */
2010
2011         desired.x = physdev->x11dev->dc_rect.left + x;
2012         desired.y = physdev->x11dev->dc_rect.top + y;
2013         current.x = current.y = 0;
2014
2015         get_xrender_color(physdev->pict_format, physdev->x11dev->textPixel, &col);
2016         tile_pict = get_tile_pict(physdev->format, &col);
2017
2018         /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
2019          */
2020         if((physdev->format == WXR_FORMAT_MONO) && (textPixel == 0))
2021             render_op = PictOpOutReverse; /* This gives us 'black' text */
2022
2023         for(idx = 0; idx < count; idx++)
2024         {
2025             elts[idx].glyphset = formatEntry->glyphset;
2026             elts[idx].chars = wstr + idx;
2027             elts[idx].nchars = 1;
2028             elts[idx].xOff = desired.x - current.x;
2029             elts[idx].yOff = desired.y - current.y;
2030
2031             current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
2032             current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
2033
2034             if(!lpDx)
2035             {
2036                 desired.x += formatEntry->gis[wstr[idx]].xOff;
2037                 desired.y += formatEntry->gis[wstr[idx]].yOff;
2038             }
2039             else
2040             {
2041                 if(flags & ETO_PDY)
2042                 {
2043                     offset.x += lpDx[idx * 2];
2044                     offset.y += lpDx[idx * 2 + 1];
2045                 }
2046                 else
2047                     offset.x += lpDx[idx];
2048                 desired.x = physdev->x11dev->dc_rect.left + x + offset.x;
2049                 desired.y = physdev->x11dev->dc_rect.top  + y + offset.y;
2050             }
2051         }
2052
2053         if (flags & ETO_CLIPPED)
2054         {
2055             HRGN clip_region = CreateRectRgnIndirect( lprect );
2056             saved_region = add_xrender_clipping_region( physdev, clip_region );
2057             DeleteObject( clip_region );
2058         }
2059
2060         wine_tsx11_lock();
2061         /* Make sure we don't have any transforms set from a previous call */
2062         set_xrender_transformation(pict, 1, 1, 0, 0);
2063         pXRenderCompositeText16(gdi_display, render_op,
2064                                 tile_pict,
2065                                 pict,
2066                                 formatEntry->font_format,
2067                                 0, 0, 0, 0, elts, count);
2068         wine_tsx11_unlock();
2069         HeapFree(GetProcessHeap(), 0, elts);
2070         restore_xrender_clipping_region( physdev, saved_region );
2071     } else {
2072         POINT offset = {0, 0};
2073
2074         if (flags & ETO_CLIPPED)
2075         {
2076             HRGN clip_region = CreateRectRgnIndirect( lprect );
2077             saved_region = add_extra_clipping_region( physdev->x11dev, clip_region );
2078             DeleteObject( clip_region );
2079         }
2080
2081         wine_tsx11_lock();
2082         XSetForeground( gdi_display, physdev->x11dev->gc, textPixel );
2083
2084         if(aa_type == AA_None || physdev->x11dev->depth == 1)
2085         {
2086             void (* sharp_glyph_fn)(struct xrender_physdev *, INT, INT, void *, XGlyphInfo *);
2087
2088             if(aa_type == AA_None)
2089                 sharp_glyph_fn = SharpGlyphMono;
2090             else
2091                 sharp_glyph_fn = SharpGlyphGray;
2092
2093             for(idx = 0; idx < count; idx++) {
2094                 sharp_glyph_fn(physdev,
2095                                physdev->x11dev->dc_rect.left + x + offset.x,
2096                                physdev->x11dev->dc_rect.top  + y + offset.y,
2097                                formatEntry->bitmaps[wstr[idx]],
2098                                &formatEntry->gis[wstr[idx]]);
2099                 if(lpDx)
2100                 {
2101                     if(flags & ETO_PDY)
2102                     {
2103                         offset.x += lpDx[idx * 2];
2104                         offset.y += lpDx[idx * 2 + 1];
2105                     }
2106                     else
2107                         offset.x += lpDx[idx];
2108                 }
2109                 else
2110                 {
2111                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2112                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2113                 }
2114             }
2115         } else {
2116             XImage *image;
2117             int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
2118             RECT extents = {0, 0, 0, 0};
2119             POINT cur = {0, 0};
2120             int w = physdev->x11dev->drawable_rect.right - physdev->x11dev->drawable_rect.left;
2121             int h = physdev->x11dev->drawable_rect.bottom - physdev->x11dev->drawable_rect.top;
2122
2123             TRACE("drawable %dx%d\n", w, h);
2124
2125             for(idx = 0; idx < count; idx++) {
2126                 if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
2127                     extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
2128                 if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
2129                     extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
2130                 if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
2131                     extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
2132                 if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
2133                     extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
2134
2135                 if(lpDx)
2136                 {
2137                     if(flags & ETO_PDY)
2138                     {
2139                         cur.x += lpDx[idx * 2];
2140                         cur.y += lpDx[idx * 2 + 1];
2141                     }
2142                     else
2143                         cur.x += lpDx[idx];
2144                 }
2145                 else
2146                 {
2147                     cur.x += formatEntry->gis[wstr[idx]].xOff;
2148                     cur.y += formatEntry->gis[wstr[idx]].yOff;
2149                 }
2150             }
2151             TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
2152                   extents.right, extents.bottom, physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
2153
2154             if(physdev->x11dev->dc_rect.left + x + extents.left >= 0) {
2155                 image_x = physdev->x11dev->dc_rect.left + x + extents.left;
2156                 image_off_x = 0;
2157             } else {
2158                 image_x = 0;
2159                 image_off_x = physdev->x11dev->dc_rect.left + x + extents.left;
2160             }
2161             if(physdev->x11dev->dc_rect.top + y + extents.top >= 0) {
2162                 image_y = physdev->x11dev->dc_rect.top + y + extents.top;
2163                 image_off_y = 0;
2164             } else {
2165                 image_y = 0;
2166                 image_off_y = physdev->x11dev->dc_rect.top + y + extents.top;
2167             }
2168             if(physdev->x11dev->dc_rect.left + x + extents.right < w)
2169                 image_w = physdev->x11dev->dc_rect.left + x + extents.right - image_x;
2170             else
2171                 image_w = w - image_x;
2172             if(physdev->x11dev->dc_rect.top + y + extents.bottom < h)
2173                 image_h = physdev->x11dev->dc_rect.top + y + extents.bottom - image_y;
2174             else
2175                 image_h = h - image_y;
2176
2177             if(image_w <= 0 || image_h <= 0) goto no_image;
2178
2179             X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2180             image = XGetImage(gdi_display, physdev->x11dev->drawable,
2181                               image_x, image_y, image_w, image_h,
2182                               AllPlanes, ZPixmap);
2183             X11DRV_check_error();
2184
2185             TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2186                   gdi_display, (int)physdev->x11dev->drawable, image_x, image_y,
2187                   image_w, image_h, AllPlanes, ZPixmap,
2188                   physdev->x11dev->depth, image);
2189             if(!image) {
2190                 Pixmap xpm = XCreatePixmap(gdi_display, root_window, image_w, image_h,
2191                                            physdev->x11dev->depth);
2192                 GC gc;
2193                 XGCValues gcv;
2194
2195                 gcv.graphics_exposures = False;
2196                 gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
2197                 XCopyArea(gdi_display, physdev->x11dev->drawable, xpm, gc, image_x, image_y,
2198                           image_w, image_h, 0, 0);
2199                 XFreeGC(gdi_display, gc);
2200                 X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
2201                 image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
2202                                   ZPixmap);
2203                 X11DRV_check_error();
2204                 XFreePixmap(gdi_display, xpm);
2205             }
2206             if(!image) goto no_image;
2207
2208             image->red_mask = visual->red_mask;
2209             image->green_mask = visual->green_mask;
2210             image->blue_mask = visual->blue_mask;
2211
2212             for(idx = 0; idx < count; idx++) {
2213                 SmoothGlyphGray(image,
2214                                 offset.x + image_off_x - extents.left,
2215                                 offset.y + image_off_y - extents.top,
2216                                 formatEntry->bitmaps[wstr[idx]],
2217                                 &formatEntry->gis[wstr[idx]],
2218                                 physdev->x11dev->textPixel);
2219                 if(lpDx)
2220                 {
2221                     if(flags & ETO_PDY)
2222                     {
2223                         offset.x += lpDx[idx * 2];
2224                         offset.y += lpDx[idx * 2 + 1];
2225                     }
2226                     else
2227                         offset.x += lpDx[idx];
2228                 }
2229                 else
2230                 {
2231                     offset.x += formatEntry->gis[wstr[idx]].xOff;
2232                     offset.y += formatEntry->gis[wstr[idx]].yOff;
2233                 }
2234             }
2235             XPutImage(gdi_display, physdev->x11dev->drawable, physdev->x11dev->gc, image, 0, 0,
2236                       image_x, image_y, image_w, image_h);
2237             XDestroyImage(image);
2238         }
2239     no_image:
2240         wine_tsx11_unlock();
2241         restore_clipping_region( physdev->x11dev, saved_region );
2242     }
2243     LeaveCriticalSection(&xrender_cs);
2244     retv = TRUE;
2245
2246 done_unlock:
2247     X11DRV_UnlockDIBSection( physdev->x11dev, TRUE );
2248     return retv;
2249 }
2250
2251 /* Helper function for (stretched) blitting using xrender */
2252 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
2253                           int x_src, int y_src, int x_dst, int y_dst,
2254                           double xscale, double yscale, int width, int height )
2255 {
2256     int x_offset, y_offset;
2257
2258     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2259      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2260      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2261     if(xscale != 1.0 || yscale != 1.0)
2262     {
2263         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2264          * in the wrong quadrant of the x-y plane.
2265          */
2266         x_offset = (xscale < 0) ? -width : 0;
2267         y_offset = (yscale < 0) ? -height : 0;
2268         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
2269     }
2270     else
2271     {
2272         x_offset = x_src;
2273         y_offset = y_src;
2274         set_xrender_transformation(src_pict, 1, 1, 0, 0);
2275     }
2276     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
2277                        x_offset, y_offset, 0, 0, x_dst, y_dst, width, height );
2278 }
2279
2280 /* Helper function for (stretched) mono->color blitting using xrender */
2281 static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_pict,
2282                                int x_src, int y_src, int x_dst, int y_dst,
2283                                double xscale, double yscale, int width, int height )
2284 {
2285     int x_offset, y_offset;
2286
2287     /* When doing a mono->color blit, 'src_pict' contains a 1x1 picture for tiling, the actual
2288      * source data is in mask_pict.  The 'mask_pict' data effectively acts as an alpha channel to the
2289      * tile data. We need PictOpOver for correct rendering.
2290      * Note since the 'source data' is in the mask picture, we have to pass x_src / y_src using
2291      * mask_x / mask_y
2292      */
2293     if (xscale != 1.0 || yscale != 1.0)
2294     {
2295         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2296          * in the wrong quadrant of the x-y plane.
2297          */
2298         x_offset = (xscale < 0) ? -width : 0;
2299         y_offset = (yscale < 0) ? -height : 0;
2300         set_xrender_transformation(mask_pict, xscale, yscale, x_src, y_src);
2301     }
2302     else
2303     {
2304         x_offset = x_src;
2305         y_offset = y_src;
2306         set_xrender_transformation(mask_pict, 1, 1, 0, 0);
2307     }
2308     pXRenderComposite(gdi_display, PictOpOver, src_pict, mask_pict, dst_pict,
2309                       0, 0, x_offset, y_offset, x_dst, y_dst, width, height );
2310 }
2311
2312 static void get_colors( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
2313                         XRenderColor *fg, XRenderColor *bg )
2314 {
2315     if (physdev_src->format == WXR_FORMAT_MONO)
2316     {
2317         RGBQUAD rgb[2];
2318         int pixel;
2319
2320         if (GetDIBColorTable( physdev_src->dev.hdc, 0, 2, rgb ) == 2)
2321         {
2322             pixel = X11DRV_PALETTE_ToPhysical( physdev_dst->x11dev,
2323                                                RGB( rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue ));
2324             get_xrender_color( physdev_dst->pict_format, pixel, fg );
2325             pixel = X11DRV_PALETTE_ToPhysical( physdev_dst->x11dev,
2326                                                RGB( rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue ));
2327             get_xrender_color( physdev_dst->pict_format, pixel, bg );
2328             return;
2329         }
2330     }
2331     get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->textPixel, fg );
2332     get_xrender_color( physdev_dst->pict_format, physdev_dst->x11dev->backgroundPixel, bg );
2333 }
2334
2335 static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
2336                                   Drawable drawable, const struct bitblt_coords *src,
2337                                   const struct bitblt_coords *dst )
2338 {
2339     int width = abs( dst->width );
2340     int height = abs( dst->height );
2341     int x_src = physdev_src->x11dev->dc_rect.left + src->x;
2342     int y_src = physdev_src->x11dev->dc_rect.top + src->y;
2343     int x_dst, y_dst;
2344     Picture src_pict = 0, dst_pict, mask_pict = 0;
2345     BOOL use_repeat;
2346     double xscale, yscale;
2347
2348     use_repeat = use_source_repeat( physdev_src );
2349     if (!use_repeat)
2350     {
2351         xscale = src->width / (double)dst->width;
2352         yscale = src->height / (double)dst->height;
2353     }
2354     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2355
2356     if (drawable)  /* using an intermediate pixmap */
2357     {
2358         XRenderPictureAttributes pa;
2359
2360         x_dst = dst->x;
2361         y_dst = dst->y;
2362         pa.repeat = RepeatNone;
2363         wine_tsx11_lock();
2364         dst_pict = pXRenderCreatePicture( gdi_display, drawable, physdev_dst->pict_format, CPRepeat, &pa );
2365         wine_tsx11_unlock();
2366     }
2367     else
2368     {
2369         x_dst = physdev_dst->x11dev->dc_rect.left + dst->x;
2370         y_dst = physdev_dst->x11dev->dc_rect.top + dst->y;
2371         dst_pict = get_xrender_picture( physdev_dst );
2372     }
2373
2374     if (src->width < 0) x_src += src->width + 1;
2375     if (src->height < 0) y_src += src->height + 1;
2376     if (dst->width < 0) x_dst += dst->width + 1;
2377     if (dst->height < 0) y_dst += dst->height + 1;
2378
2379     /* mono -> color */
2380     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
2381     {
2382         XRenderColor fg, bg;
2383
2384         get_colors( physdev_src, physdev_dst, &fg, &bg );
2385         fg.alpha = bg.alpha = 0;
2386
2387         /* We use the source drawable as a mask */
2388         mask_pict = get_xrender_picture_source( physdev_src, use_repeat );
2389
2390         /* Use backgroundPixel as the foreground color */
2391         EnterCriticalSection( &xrender_cs );
2392         src_pict = get_tile_pict( physdev_dst->format, &bg );
2393
2394         /* Create a destination picture and fill it with textPixel color as the background color */
2395         wine_tsx11_lock();
2396         pXRenderFillRectangle( gdi_display, PictOpSrc, dst_pict, &fg, x_dst, y_dst, width, height );
2397
2398         xrender_mono_blit( src_pict, mask_pict, dst_pict, x_src, y_src,
2399                            x_dst, y_dst, xscale, yscale, width, height );
2400
2401         wine_tsx11_unlock();
2402         LeaveCriticalSection( &xrender_cs );
2403     }
2404     else /* color -> color (can be at different depths) or mono -> mono */
2405     {
2406         if (physdev_dst->x11dev->depth == 32 && physdev_src->x11dev->depth < 32)
2407             mask_pict = get_no_alpha_mask();
2408         src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2409
2410         wine_tsx11_lock();
2411
2412         xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict,
2413                       x_src, y_src, x_dst, y_dst, xscale, yscale, width, height );
2414
2415         wine_tsx11_unlock();
2416     }
2417
2418     if (drawable)
2419     {
2420         wine_tsx11_lock();
2421         pXRenderFreePicture( gdi_display, dst_pict );
2422         wine_tsx11_unlock();
2423     }
2424 }
2425
2426
2427 /***********************************************************************
2428  *           xrenderdrv_StretchBlt
2429  */
2430 static BOOL xrenderdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
2431                                    PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
2432 {
2433     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2434     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2435     INT sSrc, sDst;
2436     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
2437
2438     if (src_dev->funcs != dst_dev->funcs)
2439     {
2440         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
2441         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
2442     }
2443
2444     if (!X11DRV_XRender_Installed) goto x11drv_fallback;
2445
2446     /* XRender is of no use for color -> mono */
2447     if (physdev_dst->format == WXR_FORMAT_MONO && physdev_src->format != WXR_FORMAT_MONO)
2448         goto x11drv_fallback;
2449
2450     /* if not stretching, we only need to handle format conversion */
2451     if (!stretch && physdev_dst->format == physdev_src->format) goto x11drv_fallback;
2452
2453     sSrc = sDst = X11DRV_LockDIBSection( physdev_dst->x11dev, DIB_Status_None );
2454     if (physdev_dst != physdev_src) sSrc = X11DRV_LockDIBSection( physdev_src->x11dev, DIB_Status_None );
2455
2456     /* try client-side DIB copy */
2457     if (!stretch && sSrc == DIB_Status_AppMod)
2458     {
2459         if (physdev_dst != physdev_src) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2460         X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2461         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
2462         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
2463     }
2464
2465     X11DRV_CoerceDIBSection( physdev_dst->x11dev, DIB_Status_GdiMod );
2466     if (physdev_dst != physdev_src) X11DRV_CoerceDIBSection( physdev_src->x11dev, DIB_Status_GdiMod );
2467
2468     if (rop != SRCCOPY)
2469     {
2470         GC tmpGC;
2471         Pixmap tmp_pixmap;
2472         struct bitblt_coords tmp;
2473
2474         /* make coordinates relative to tmp pixmap */
2475         tmp = *dst;
2476         tmp.x -= tmp.visrect.left;
2477         tmp.y -= tmp.visrect.top;
2478         OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
2479
2480         wine_tsx11_lock();
2481         tmpGC = XCreateGC( gdi_display, physdev_dst->x11dev->drawable, 0, NULL );
2482         XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
2483         XSetGraphicsExposures( gdi_display, tmpGC, False );
2484         tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
2485                                     tmp.visrect.bottom - tmp.visrect.top, physdev_dst->x11dev->depth );
2486         wine_tsx11_unlock();
2487
2488         xrender_stretch_blit( physdev_src, physdev_dst, tmp_pixmap, src, &tmp );
2489         execute_rop( physdev_dst->x11dev, tmp_pixmap, tmpGC, &dst->visrect, rop );
2490
2491         wine_tsx11_lock();
2492         XFreePixmap( gdi_display, tmp_pixmap );
2493         XFreeGC( gdi_display, tmpGC );
2494         wine_tsx11_unlock();
2495     }
2496     else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
2497
2498     if (physdev_dst != physdev_src) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2499     X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2500     return TRUE;
2501
2502 x11drv_fallback:
2503     return X11DRV_StretchBlt( &physdev_dst->x11dev->dev, dst, &physdev_src->x11dev->dev, src, rop );
2504 }
2505
2506
2507 /***********************************************************************
2508  *           xrenderdrv_AlphaBlend
2509  */
2510 static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
2511                                    PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
2512 {
2513     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
2514     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
2515     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
2516     double xscale, yscale;
2517     BOOL use_repeat;
2518
2519     if (!X11DRV_XRender_Installed || src_dev->funcs != dst_dev->funcs)
2520     {
2521         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pAlphaBlend );
2522         return dst_dev->funcs->pAlphaBlend( dst_dev, dst, src_dev, src, blendfn );
2523     }
2524
2525     if (physdev_src != physdev_dst) X11DRV_LockDIBSection( physdev_src->x11dev, DIB_Status_GdiMod );
2526     X11DRV_LockDIBSection( physdev_dst->x11dev, DIB_Status_GdiMod );
2527
2528     dst_pict = get_xrender_picture( physdev_dst );
2529
2530     use_repeat = use_source_repeat( physdev_src );
2531     if (!use_repeat)
2532     {
2533         xscale = src->width / (double)dst->width;
2534         yscale = src->height / (double)dst->height;
2535     }
2536     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
2537
2538     if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->format)
2539     {
2540         /* we need a source picture with no alpha */
2541         enum wxr_format format = get_format_without_alpha( physdev_src->format );
2542         if (format != physdev_src->format)
2543         {
2544             XRenderPictureAttributes pa;
2545
2546             wine_tsx11_lock();
2547             pa.subwindow_mode = IncludeInferiors;
2548             pa.repeat = use_repeat ? RepeatNormal : RepeatNone;
2549             tmp_pict = pXRenderCreatePicture( gdi_display, physdev_src->x11dev->drawable,
2550                                               pict_formats[format], CPSubwindowMode|CPRepeat, &pa );
2551             wine_tsx11_unlock();
2552             src_pict = tmp_pict;
2553         }
2554     }
2555
2556     if (!src_pict) src_pict = get_xrender_picture_source( physdev_src, use_repeat );
2557
2558     EnterCriticalSection( &xrender_cs );
2559     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2560
2561     wine_tsx11_lock();
2562     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2563                   physdev_src->x11dev->dc_rect.left + src->x,
2564                   physdev_src->x11dev->dc_rect.top + src->y,
2565                   physdev_dst->x11dev->dc_rect.left + dst->x,
2566                   physdev_dst->x11dev->dc_rect.top + dst->y,
2567                   xscale, yscale, dst->width, dst->height );
2568     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2569     wine_tsx11_unlock();
2570
2571     LeaveCriticalSection( &xrender_cs );
2572     if (physdev_src != physdev_dst) X11DRV_UnlockDIBSection( physdev_src->x11dev, FALSE );
2573     X11DRV_UnlockDIBSection( physdev_dst->x11dev, TRUE );
2574     return TRUE;
2575 }
2576
2577
2578 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2579 {
2580     /* 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 */
2581     int depth = physBitmap->pixmap_depth == 1 ? 1 : physDev->depth;
2582     enum wxr_format src_format = get_xrender_format_from_color_shifts(physBitmap->pixmap_depth, &physBitmap->pixmap_color_shifts);
2583     enum wxr_format dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
2584
2585     wine_tsx11_lock();
2586     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, depth);
2587
2588     /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2589     if( (physBitmap->pixmap_depth == 1) || (!X11DRV_XRender_Installed && physDev->depth == physBitmap->pixmap_depth) ||
2590         (src_format == dst_format) )
2591     {
2592         XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2593                    get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2594     }
2595     else /* We need depth conversion */
2596     {
2597         Picture src_pict, dst_pict;
2598         XRenderPictureAttributes pa;
2599         pa.subwindow_mode = IncludeInferiors;
2600         pa.repeat = RepeatNone;
2601
2602         src_pict = pXRenderCreatePicture(gdi_display, physBitmap->pixmap,
2603                                          pict_formats[src_format], CPSubwindowMode|CPRepeat, &pa);
2604         dst_pict = pXRenderCreatePicture(gdi_display, physDev->brush.pixmap,
2605                                          pict_formats[dst_format], CPSubwindowMode|CPRepeat, &pa);
2606
2607         xrender_blit(PictOpSrc, src_pict, 0, dst_pict, 0, 0, 0, 0, 1.0, 1.0, width, height);
2608         pXRenderFreePicture(gdi_display, src_pict);
2609         pXRenderFreePicture(gdi_display, dst_pict);
2610     }
2611     wine_tsx11_unlock();
2612 }
2613
2614 static const struct gdi_dc_funcs xrender_funcs =
2615 {
2616     NULL,                               /* pAbortDoc */
2617     NULL,                               /* pAbortPath */
2618     xrenderdrv_AlphaBlend,              /* pAlphaBlend */
2619     NULL,                               /* pAngleArc */
2620     NULL,                               /* pArc */
2621     NULL,                               /* pArcTo */
2622     NULL,                               /* pBeginPath */
2623     NULL,                               /* pBlendImage */
2624     NULL,                               /* pChoosePixelFormat */
2625     NULL,                               /* pChord */
2626     NULL,                               /* pCloseFigure */
2627     xrenderdrv_CreateBitmap,            /* pCreateBitmap */
2628     xrenderdrv_CreateCompatibleDC,      /* pCreateCompatibleDC */
2629     xrenderdrv_CreateDC,                /* pCreateDC */
2630     NULL,                               /* pCreateDIBSection */
2631     xrenderdrv_DeleteBitmap,            /* pDeleteBitmap */
2632     xrenderdrv_DeleteDC,                /* pDeleteDC */
2633     NULL,                               /* pDeleteObject */
2634     NULL,                               /* pDescribePixelFormat */
2635     NULL,                               /* pDeviceCapabilities */
2636     NULL,                               /* pEllipse */
2637     NULL,                               /* pEndDoc */
2638     NULL,                               /* pEndPage */
2639     NULL,                               /* pEndPath */
2640     NULL,                               /* pEnumDeviceFonts */
2641     NULL,                               /* pEnumICMProfiles */
2642     NULL,                               /* pExcludeClipRect */
2643     NULL,                               /* pExtDeviceMode */
2644     xrenderdrv_ExtEscape,               /* pExtEscape */
2645     NULL,                               /* pExtFloodFill */
2646     NULL,                               /* pExtSelectClipRgn */
2647     xrenderdrv_ExtTextOut,              /* pExtTextOut */
2648     NULL,                               /* pFillPath */
2649     NULL,                               /* pFillRgn */
2650     NULL,                               /* pFlattenPath */
2651     NULL,                               /* pFrameRgn */
2652     NULL,                               /* pGdiComment */
2653     NULL,                               /* pGetCharWidth */
2654     NULL,                               /* pGetDeviceCaps */
2655     NULL,                               /* pGetDeviceGammaRamp */
2656     NULL,                               /* pGetICMProfile */
2657     xrenderdrv_GetImage,                /* pGetImage */
2658     NULL,                               /* pGetNearestColor */
2659     NULL,                               /* pGetPixel */
2660     NULL,                               /* pGetPixelFormat */
2661     NULL,                               /* pGetSystemPaletteEntries */
2662     NULL,                               /* pGetTextExtentExPoint */
2663     NULL,                               /* pGetTextMetrics */
2664     NULL,                               /* pIntersectClipRect */
2665     NULL,                               /* pInvertRgn */
2666     NULL,                               /* pLineTo */
2667     NULL,                               /* pModifyWorldTransform */
2668     NULL,                               /* pMoveTo */
2669     NULL,                               /* pOffsetClipRgn */
2670     NULL,                               /* pOffsetViewportOrg */
2671     NULL,                               /* pOffsetWindowOrg */
2672     NULL,                               /* pPaintRgn */
2673     NULL,                               /* pPatBlt */
2674     NULL,                               /* pPie */
2675     NULL,                               /* pPolyBezier */
2676     NULL,                               /* pPolyBezierTo */
2677     NULL,                               /* pPolyDraw */
2678     NULL,                               /* pPolyPolygon */
2679     NULL,                               /* pPolyPolyline */
2680     NULL,                               /* pPolygon */
2681     NULL,                               /* pPolyline */
2682     NULL,                               /* pPolylineTo */
2683     xrenderdrv_PutImage,                /* pPutImage */
2684     NULL,                               /* pRealizeDefaultPalette */
2685     NULL,                               /* pRealizePalette */
2686     NULL,                               /* pRectangle */
2687     NULL,                               /* pResetDC */
2688     NULL,                               /* pRestoreDC */
2689     NULL,                               /* pRoundRect */
2690     NULL,                               /* pSaveDC */
2691     NULL,                               /* pScaleViewportExt */
2692     NULL,                               /* pScaleWindowExt */
2693     xrenderdrv_SelectBitmap,            /* pSelectBitmap */
2694     NULL,                               /* pSelectBrush */
2695     NULL,                               /* pSelectClipPath */
2696     xrenderdrv_SelectFont,              /* pSelectFont */
2697     NULL,                               /* pSelectPalette */
2698     NULL,                               /* pSelectPen */
2699     NULL,                               /* pSetArcDirection */
2700     NULL,                               /* pSetBkColor */
2701     NULL,                               /* pSetBkMode */
2702     NULL,                               /* pSetDCBrushColor */
2703     NULL,                               /* pSetDCPenColor */
2704     NULL,                               /* pSetDIBColorTable */
2705     NULL,                               /* pSetDIBitsToDevice */
2706     xrenderdrv_SetDeviceClipping,       /* pSetDeviceClipping */
2707     NULL,                               /* pSetDeviceGammaRamp */
2708     NULL,                               /* pSetLayout */
2709     NULL,                               /* pSetMapMode */
2710     NULL,                               /* pSetMapperFlags */
2711     NULL,                               /* pSetPixel */
2712     NULL,                               /* pSetPixelFormat */
2713     NULL,                               /* pSetPolyFillMode */
2714     NULL,                               /* pSetROP2 */
2715     NULL,                               /* pSetRelAbs */
2716     NULL,                               /* pSetStretchBltMode */
2717     NULL,                               /* pSetTextAlign */
2718     NULL,                               /* pSetTextCharacterExtra */
2719     NULL,                               /* pSetTextColor */
2720     NULL,                               /* pSetTextJustification */
2721     NULL,                               /* pSetViewportExt */
2722     NULL,                               /* pSetViewportOrg */
2723     NULL,                               /* pSetWindowExt */
2724     NULL,                               /* pSetWindowOrg */
2725     NULL,                               /* pSetWorldTransform */
2726     NULL,                               /* pStartDoc */
2727     NULL,                               /* pStartPage */
2728     xrenderdrv_StretchBlt,              /* pStretchBlt */
2729     NULL,                               /* pStretchDIBits */
2730     NULL,                               /* pStrokeAndFillPath */
2731     NULL,                               /* pStrokePath */
2732     NULL,                               /* pSwapBuffers */
2733     NULL,                               /* pUnrealizePalette */
2734     NULL,                               /* pWidenPath */
2735     /* OpenGL not supported */
2736 };
2737
2738 #else /* SONAME_LIBXRENDER */
2739
2740 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
2741 {
2742     TRACE("XRender support not compiled in.\n");
2743     return NULL;
2744 }
2745
2746 void X11DRV_XRender_Finalize(void)
2747 {
2748 }
2749
2750 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE *physDev, X_PHYSBITMAP *physBitmap, int width, int height)
2751 {
2752     wine_tsx11_lock();
2753     physDev->brush.pixmap = XCreatePixmap(gdi_display, root_window, width, height, physBitmap->pixmap_depth);
2754
2755     XCopyArea( gdi_display, physBitmap->pixmap, physDev->brush.pixmap,
2756                get_bitmap_gc(physBitmap->pixmap_depth), 0, 0, width, height, 0, 0 );
2757     wine_tsx11_unlock();
2758 }
2759
2760 BOOL X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP *physBitmap, int bits_pixel, const DIBSECTION *dib)
2761 {
2762     return FALSE;
2763 }
2764
2765 #endif /* SONAME_LIBXRENDER */