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