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