amstream: Fix return value of BasePinImp_GetMediaType.
[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 WINE_DEFAULT_DEBUG_CHANNEL(xrender);
42
43 #ifdef SONAME_LIBXRENDER
44
45 WINE_DECLARE_DEBUG_CHANNEL(winediag);
46
47 #include <X11/Xlib.h>
48 #include <X11/extensions/Xrender.h>
49
50 #ifndef RepeatNone  /* added in 0.10 */
51 #define RepeatNone    0
52 #define RepeatNormal  1
53 #define RepeatPad     2
54 #define RepeatReflect 3
55 #endif
56
57 enum wxr_format
58 {
59   WXR_FORMAT_MONO,
60   WXR_FORMAT_GRAY,
61   WXR_FORMAT_X1R5G5B5,
62   WXR_FORMAT_X1B5G5R5,
63   WXR_FORMAT_R5G6B5,
64   WXR_FORMAT_B5G6R5,
65   WXR_FORMAT_R8G8B8,
66   WXR_FORMAT_B8G8R8,
67   WXR_FORMAT_A8R8G8B8,
68   WXR_FORMAT_B8G8R8A8,
69   WXR_FORMAT_X8R8G8B8,
70   WXR_FORMAT_B8G8R8X8,
71   WXR_NB_FORMATS,
72   WXR_INVALID_FORMAT = WXR_NB_FORMATS
73 };
74
75 typedef struct wine_xrender_format_template
76 {
77     unsigned int depth;
78     unsigned int alpha;
79     unsigned int alphaMask;
80     unsigned int red;
81     unsigned int redMask;
82     unsigned int green;
83     unsigned int greenMask;
84     unsigned int blue;
85     unsigned int blueMask;
86 } WineXRenderFormatTemplate;
87
88 static const WineXRenderFormatTemplate wxr_formats_template[WXR_NB_FORMATS] =
89 {
90     /* Format               depth   alpha   mask    red     mask    green   mask    blue    mask*/
91 /* WXR_FORMAT_MONO     */ { 1,      0,      0x01,   0,      0,      0,      0,      0,      0       },
92 /* WXR_FORMAT_GRAY     */ { 8,      0,      0xff,   0,      0,      0,      0,      0,      0       },
93 /* WXR_FORMAT_X1R5G5B5 */ { 16,     0,      0,      10,     0x1f,   5,      0x1f,   0,      0x1f    },
94 /* WXR_FORMAT_X1B5G5R5 */ { 16,     0,      0,      0,      0x1f,   5,      0x1f,   10,     0x1f    },
95 /* WXR_FORMAT_R5G6B5   */ { 16,     0,      0,      11,     0x1f,   5,      0x3f,   0,      0x1f    },
96 /* WXR_FORMAT_B5G6R5   */ { 16,     0,      0,      0,      0x1f,   5,      0x3f,   11,     0x1f    },
97 /* WXR_FORMAT_R8G8B8   */ { 24,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
98 /* WXR_FORMAT_B8G8R8   */ { 24,     0,      0,      0,      0xff,   8,      0xff,   16,     0xff    },
99 /* WXR_FORMAT_A8R8G8B8 */ { 32,     24,     0xff,   16,     0xff,   8,      0xff,   0,      0xff    },
100 /* WXR_FORMAT_B8G8R8A8 */ { 32,     0,      0xff,   8,      0xff,   16,     0xff,   24,     0xff    },
101 /* WXR_FORMAT_X8R8G8B8 */ { 32,     0,      0,      16,     0xff,   8,      0xff,   0,      0xff    },
102 /* WXR_FORMAT_B8G8R8X8 */ { 32,     0,      0,      8,      0xff,   16,     0xff,   24,     0xff    },
103 };
104
105 static const ColorShifts wxr_color_shifts[WXR_NB_FORMATS] =
106 {
107     /* format                phys red    phys green  phys blue   log red     log green   log blue */
108 /* WXR_FORMAT_MONO     */ { { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 }  },
109 /* WXR_FORMAT_GRAY     */ { { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 },  { 0,0,0 }  },
110 /* WXR_FORMAT_X1R5G5B5 */ { {10,5,31},  { 5,5,31},  { 0,5,31},  {10,5,31},  { 5,5,31},  { 0,5,31}  },
111 /* WXR_FORMAT_X1B5G5R5 */ { { 0,5,31},  { 5,5,31},  {10,5,31},  { 0,5,31},  { 5,5,31},  {10,5,31}  },
112 /* WXR_FORMAT_R5G6B5   */ { {11,5,31},  { 5,6,63},  { 0,5,31},  {11,5,31},  { 5,6,63},  { 0,5,31}  },
113 /* WXR_FORMAT_B5G6R5   */ { { 0,5,31},  { 5,6,63},  {11,5,31},  { 0,5,31},  { 5,6,63},  {11,5,31}  },
114 /* WXR_FORMAT_R8G8B8   */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
115 /* WXR_FORMAT_B8G8R8   */ { { 0,8,255}, { 8,8,255}, {16,8,255}, { 0,8,255}, { 8,8,255}, {16,8,255} },
116 /* WXR_FORMAT_A8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
117 /* WXR_FORMAT_B8G8R8A8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
118 /* WXR_FORMAT_X8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
119 /* WXR_FORMAT_B8G8R8X8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
120 };
121
122 static enum wxr_format default_format = WXR_INVALID_FORMAT;
123 static XRenderPictFormat *pict_formats[WXR_NB_FORMATS + 1 /* invalid format */];
124
125 typedef struct
126 {
127     LOGFONTW lf;
128     XFORM    xform;
129     SIZE     devsize;  /* size in device coords */
130     DWORD    hash;
131 } LFANDSIZE;
132
133 #define INITIAL_REALIZED_BUF_SIZE 128
134
135 typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
136
137 typedef struct
138 {
139     GlyphSet glyphset;
140     XRenderPictFormat *font_format;
141     int nrealized;
142     BOOL *realized;
143     XGlyphInfo *gis;
144 } gsCacheEntryFormat;
145
146 typedef struct
147 {
148     LFANDSIZE lfsz;
149     gsCacheEntryFormat * format[AA_MAXVALUE];
150     INT count;
151     INT next;
152 } gsCacheEntry;
153
154 struct xrender_physdev
155 {
156     struct gdi_physdev dev;
157     X11DRV_PDEVICE    *x11dev;
158     HRGN               region;
159     enum wxr_format    format;
160     UINT               aa_flags;
161     int                cache_index;
162     BOOL               update_clip;
163     Picture            pict;
164     Picture            pict_src;
165     XRenderPictFormat *pict_format;
166 };
167
168 static inline struct xrender_physdev *get_xrender_dev( PHYSDEV dev )
169 {
170     return (struct xrender_physdev *)dev;
171 }
172
173 static const struct gdi_dc_funcs xrender_funcs;
174
175 static gsCacheEntry *glyphsetCache = NULL;
176 static DWORD glyphsetCacheSize = 0;
177 static INT lastfree = -1;
178 static INT mru = -1;
179
180 #define INIT_CACHE_SIZE 10
181
182 static void *xrender_handle;
183
184 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
185 MAKE_FUNCPTR(XRenderAddGlyphs)
186 MAKE_FUNCPTR(XRenderChangePicture)
187 MAKE_FUNCPTR(XRenderComposite)
188 MAKE_FUNCPTR(XRenderCompositeText16)
189 MAKE_FUNCPTR(XRenderCreateGlyphSet)
190 MAKE_FUNCPTR(XRenderCreatePicture)
191 MAKE_FUNCPTR(XRenderFillRectangle)
192 MAKE_FUNCPTR(XRenderFindFormat)
193 MAKE_FUNCPTR(XRenderFindVisualFormat)
194 MAKE_FUNCPTR(XRenderFreeGlyphSet)
195 MAKE_FUNCPTR(XRenderFreePicture)
196 MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
197 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
198 MAKE_FUNCPTR(XRenderCreateLinearGradient)
199 #endif
200 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
201 MAKE_FUNCPTR(XRenderSetPictureTransform)
202 #endif
203 MAKE_FUNCPTR(XRenderQueryExtension)
204
205 #undef MAKE_FUNCPTR
206
207 static CRITICAL_SECTION xrender_cs;
208 static CRITICAL_SECTION_DEBUG critsect_debug =
209 {
210     0, 0, &xrender_cs,
211     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
212       0, 0, { (DWORD_PTR)(__FILE__ ": xrender_cs") }
213 };
214 static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
215
216 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
217           ( ( (ULONG)_x4 << 24 ) |     \
218             ( (ULONG)_x3 << 16 ) |     \
219             ( (ULONG)_x2 <<  8 ) |     \
220               (ULONG)_x1         )
221
222 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
223
224 #define GASP_GRIDFIT 0x01
225 #define GASP_DOGRAY  0x02
226
227 #ifdef WORDS_BIGENDIAN
228 #define get_be_word(x) (x)
229 #define NATIVE_BYTE_ORDER MSBFirst
230 #else
231 #define get_be_word(x) RtlUshortByteSwap(x)
232 #define NATIVE_BYTE_ORDER LSBFirst
233 #endif
234
235 static BOOL has_alpha( enum wxr_format format )
236 {
237     return (format == WXR_FORMAT_A8R8G8B8 || format == WXR_FORMAT_B8G8R8A8);
238 }
239
240 static enum wxr_format get_format_without_alpha( enum wxr_format format )
241 {
242     switch (format)
243     {
244     case WXR_FORMAT_A8R8G8B8: return WXR_FORMAT_X8R8G8B8;
245     case WXR_FORMAT_B8G8R8A8: return WXR_FORMAT_B8G8R8X8;
246     default: return format;
247     }
248 }
249
250 static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
251 {
252     templ->id = 0;
253     templ->type = PictTypeDirect;
254     templ->depth = fmt->depth;
255     templ->direct.alpha = fmt->alpha;
256     templ->direct.alphaMask = fmt->alphaMask;
257     templ->direct.red = fmt->red;
258     templ->direct.redMask = fmt->redMask;
259     templ->direct.green = fmt->green;
260     templ->direct.greenMask = fmt->greenMask;
261     templ->direct.blue = fmt->blue;
262     templ->direct.blueMask = fmt->blueMask;
263     templ->colormap = 0;
264
265     *mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
266
267     return TRUE;
268 }
269
270 static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
271 {
272     if(fmt->depth != default_visual.depth) return FALSE;
273     if( (fmt->redMask << fmt->red) != default_visual.red_mask) return FALSE;
274     if( (fmt->greenMask << fmt->green) != default_visual.green_mask) return FALSE;
275     if( (fmt->blueMask << fmt->blue) != default_visual.blue_mask) return FALSE;
276
277     /* We never select a default ARGB visual */
278     if(fmt->alphaMask) return FALSE;
279     return TRUE;
280 }
281
282 static int load_xrender_formats(void)
283 {
284     int count = 0;
285     unsigned int i;
286
287     for (i = 0; i < WXR_NB_FORMATS; i++)
288     {
289         XRenderPictFormat templ;
290
291         if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
292         {
293             pict_formats[i] = pXRenderFindVisualFormat(gdi_display, default_visual.visual);
294             if (!pict_formats[i])
295             {
296                 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
297                 if (default_visual.class == DirectColor)
298                 {
299                     XVisualInfo info;
300                     if (XMatchVisualInfo( gdi_display, default_visual.screen,
301                                           default_visual.depth, TrueColor, &info ))
302                     {
303                         pict_formats[i] = pXRenderFindVisualFormat(gdi_display, info.visual);
304                         if (pict_formats[i]) default_visual = info;
305                     }
306                 }
307             }
308             if (pict_formats[i]) default_format = i;
309         }
310         else
311         {
312             unsigned long mask = 0;
313             get_xrender_template(&wxr_formats_template[i], &templ, &mask);
314             pict_formats[i] = pXRenderFindFormat(gdi_display, mask, &templ, 0);
315         }
316         if (pict_formats[i])
317         {
318             count++;
319             TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats[i]->id, i);
320         }
321     }
322     return count;
323 }
324
325 /***********************************************************************
326  *   X11DRV_XRender_Init
327  *
328  * Let's see if our XServer has the extension available
329  *
330  */
331 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
332 {
333     int event_base, i;
334
335     if (!client_side_with_render) return NULL;
336     if (!(xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0))) return NULL;
337
338 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) return NULL
339 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0)
340     LOAD_FUNCPTR(XRenderAddGlyphs);
341     LOAD_FUNCPTR(XRenderChangePicture);
342     LOAD_FUNCPTR(XRenderComposite);
343     LOAD_FUNCPTR(XRenderCompositeText16);
344     LOAD_FUNCPTR(XRenderCreateGlyphSet);
345     LOAD_FUNCPTR(XRenderCreatePicture);
346     LOAD_FUNCPTR(XRenderFillRectangle);
347     LOAD_FUNCPTR(XRenderFindFormat);
348     LOAD_FUNCPTR(XRenderFindVisualFormat);
349     LOAD_FUNCPTR(XRenderFreeGlyphSet);
350     LOAD_FUNCPTR(XRenderFreePicture);
351     LOAD_FUNCPTR(XRenderSetPictureClipRectangles);
352     LOAD_FUNCPTR(XRenderQueryExtension);
353 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
354     LOAD_OPTIONAL_FUNCPTR(XRenderCreateLinearGradient);
355 #endif
356 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
357     LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform);
358 #endif
359 #undef LOAD_OPTIONAL_FUNCPTR
360 #undef LOAD_FUNCPTR
361
362     if (!pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base)) return NULL;
363
364     TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
365     if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
366     {
367         ERR_(winediag)("Wine has detected that you probably have a buggy version "
368                        "of libXrender.  Because of this client side font rendering "
369                        "will be disabled.  Please upgrade this library.\n");
370         return NULL;
371     }
372
373     if (!default_visual.red_mask || !default_visual.green_mask || !default_visual.blue_mask)
374     {
375         WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
376         return NULL;
377     }
378
379     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
380                               sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
381
382     glyphsetCacheSize = INIT_CACHE_SIZE;
383     lastfree = 0;
384     for(i = 0; i < INIT_CACHE_SIZE; i++) {
385         glyphsetCache[i].next = i + 1;
386         glyphsetCache[i].count = -1;
387     }
388     glyphsetCache[i-1].next = -1;
389
390     return &xrender_funcs;
391 }
392
393 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
394 static void get_xrender_color( struct xrender_physdev *physdev, COLORREF src_color, XRenderColor *dst_color )
395 {
396     if (src_color & (1 << 24))  /* PALETTEINDEX */
397     {
398         HPALETTE pal = GetCurrentObject( physdev->dev.hdc, OBJ_PAL );
399         PALETTEENTRY pal_ent;
400
401         if (!GetPaletteEntries( pal, LOWORD(src_color), 1, &pal_ent ))
402             GetPaletteEntries( pal, 0, 1, &pal_ent );
403         dst_color->red   = pal_ent.peRed   * 257;
404         dst_color->green = pal_ent.peGreen * 257;
405         dst_color->blue  = pal_ent.peBlue  * 257;
406     }
407     else
408     {
409         if (src_color >> 16 == 0x10ff) src_color = 0; /* DIBINDEX */
410
411         dst_color->red   = GetRValue( src_color ) * 257;
412         dst_color->green = GetGValue( src_color ) * 257;
413         dst_color->blue  = GetBValue( src_color ) * 257;
414     }
415
416     if (physdev->format == WXR_FORMAT_MONO && !dst_color->red && !dst_color->green && !dst_color->blue)
417         dst_color->alpha = 0;
418     else
419         dst_color->alpha = 0xffff;
420 }
421
422 static enum wxr_format get_xrender_format_from_bitmapinfo( const BITMAPINFO *info )
423 {
424     if (info->bmiHeader.biPlanes != 1) return WXR_INVALID_FORMAT;
425
426     switch (info->bmiHeader.biBitCount)
427     {
428     case 1:
429         return WXR_FORMAT_MONO;
430     case 4:
431     case 8:
432         break;
433     case 24:
434         if (info->bmiHeader.biCompression != BI_RGB) break;
435         return WXR_FORMAT_R8G8B8;
436     case 16:
437     case 32:
438         if (info->bmiHeader.biCompression == BI_BITFIELDS)
439         {
440             DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
441             unsigned int i;
442
443             for (i = 0; i < WXR_NB_FORMATS; i++)
444             {
445                 if (info->bmiHeader.biBitCount == wxr_formats_template[i].depth &&
446                     colors[0] == (wxr_formats_template[i].redMask << wxr_formats_template[i].red) &&
447                     colors[1] == (wxr_formats_template[i].greenMask << wxr_formats_template[i].green) &&
448                     colors[2] == (wxr_formats_template[i].blueMask << wxr_formats_template[i].blue))
449                     return i;
450             }
451             break;
452         }
453         if (info->bmiHeader.biCompression != BI_RGB) break;
454         return (info->bmiHeader.biBitCount == 16) ? WXR_FORMAT_X1R5G5B5 : WXR_FORMAT_A8R8G8B8;
455     }
456     return WXR_INVALID_FORMAT;
457 }
458
459 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
460 static void set_xrender_transformation(Picture src_pict, double xscale, double yscale, int xoffset, int yoffset)
461 {
462 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
463     XTransform xform = {{
464         { XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(xoffset) },
465         { XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(yoffset) },
466         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
467     }};
468
469     pXRenderSetPictureTransform(gdi_display, src_pict, &xform);
470 #endif
471 }
472
473 static void update_xrender_clipping( struct xrender_physdev *dev, HRGN rgn )
474 {
475     XRenderPictureAttributes pa;
476     RGNDATA *data;
477
478     if (!rgn)
479     {
480         pa.clip_mask = None;
481         pXRenderChangePicture( gdi_display, dev->pict, CPClipMask, &pa );
482     }
483     else if ((data = X11DRV_GetRegionData( rgn, 0 )))
484     {
485         pXRenderSetPictureClipRectangles( gdi_display, dev->pict,
486                                           dev->x11dev->dc_rect.left, dev->x11dev->dc_rect.top,
487                                           (XRectangle *)data->Buffer, data->rdh.nCount );
488         HeapFree( GetProcessHeap(), 0, data );
489     }
490 }
491
492
493 static Picture get_xrender_picture( struct xrender_physdev *dev, HRGN clip_rgn, const RECT *clip_rect )
494 {
495     if (!dev->pict && dev->pict_format)
496     {
497         XRenderPictureAttributes pa;
498
499         pa.subwindow_mode = IncludeInferiors;
500         dev->pict = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
501                                            dev->pict_format, CPSubwindowMode, &pa );
502         TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
503                dev->pict, dev->dev.hdc, dev->x11dev->drawable );
504         dev->update_clip = (dev->region != 0);
505     }
506
507     if (clip_rect)
508     {
509         HRGN rgn = CreateRectRgnIndirect( clip_rect );
510         if (clip_rgn) CombineRgn( rgn, rgn, clip_rgn, RGN_AND );
511         if (dev->region) CombineRgn( rgn, rgn, dev->region, RGN_AND );
512         update_xrender_clipping( dev, rgn );
513         DeleteObject( rgn );
514     }
515     else if (clip_rgn)
516     {
517         if (dev->region)
518         {
519             HRGN rgn = CreateRectRgn( 0, 0, 0, 0 );
520             CombineRgn( rgn, clip_rgn, dev->region, RGN_AND );
521             update_xrender_clipping( dev, rgn );
522             DeleteObject( rgn );
523         }
524         else update_xrender_clipping( dev, clip_rgn );
525     }
526     else if (dev->update_clip) update_xrender_clipping( dev, dev->region );
527
528     dev->update_clip = (clip_rect || clip_rgn);  /* have to update again if we are using a custom region */
529     return dev->pict;
530 }
531
532 static Picture get_xrender_picture_source( struct xrender_physdev *dev, BOOL repeat )
533 {
534     if (!dev->pict_src && dev->pict_format)
535     {
536         XRenderPictureAttributes pa;
537
538         pa.subwindow_mode = IncludeInferiors;
539         pa.repeat = repeat ? RepeatNormal : RepeatNone;
540         dev->pict_src = pXRenderCreatePicture( gdi_display, dev->x11dev->drawable,
541                                                dev->pict_format, CPSubwindowMode|CPRepeat, &pa );
542
543         TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
544               dev->pict_src, dev->dev.hdc, dev->x11dev->drawable, pa.repeat);
545     }
546
547     return dev->pict_src;
548 }
549
550 static void free_xrender_picture( struct xrender_physdev *dev )
551 {
552     if (dev->pict || dev->pict_src)
553     {
554         XFlush( gdi_display );
555         if (dev->pict)
556         {
557             TRACE("freeing pict = %lx dc = %p\n", dev->pict, dev->dev.hdc);
558             pXRenderFreePicture(gdi_display, dev->pict);
559             dev->pict = 0;
560         }
561         if(dev->pict_src)
562         {
563             TRACE("freeing pict = %lx dc = %p\n", dev->pict_src, dev->dev.hdc);
564             pXRenderFreePicture(gdi_display, dev->pict_src);
565             dev->pict_src = 0;
566         }
567     }
568 }
569
570 /* return a mask picture used to force alpha to 0 */
571 static Picture get_no_alpha_mask(void)
572 {
573     static Pixmap pixmap;
574     static Picture pict;
575
576     EnterCriticalSection( &xrender_cs );
577     if (!pict)
578     {
579         XRenderPictureAttributes pa;
580         XRenderColor col;
581
582         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
583         pa.repeat = RepeatNormal;
584         pa.component_alpha = True;
585         pict = pXRenderCreatePicture( gdi_display, pixmap, pict_formats[WXR_FORMAT_A8R8G8B8],
586                                       CPRepeat|CPComponentAlpha, &pa );
587         col.red = col.green = col.blue = 0xffff;
588         col.alpha = 0;
589         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
590     }
591     LeaveCriticalSection( &xrender_cs );
592     return pict;
593 }
594
595 static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
596 {
597   if(p1->hash != p2->hash) return TRUE;
598   if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE;
599   if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE;
600   if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
601   return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName);
602 }
603
604 #if 0
605 static void walk_cache(void)
606 {
607   int i;
608
609   EnterCriticalSection(&xrender_cs);
610   for(i=mru; i >= 0; i = glyphsetCache[i].next)
611     TRACE("item %d\n", i);
612   LeaveCriticalSection(&xrender_cs);
613 }
614 #endif
615
616 static int LookupEntry(LFANDSIZE *plfsz)
617 {
618   int i, prev_i = -1;
619
620   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
621     TRACE("%d\n", i);
622     if(glyphsetCache[i].count == -1) break; /* reached free list so stop */
623
624     if(!fontcmp(&glyphsetCache[i].lfsz, plfsz)) {
625       glyphsetCache[i].count++;
626       if(prev_i >= 0) {
627         glyphsetCache[prev_i].next = glyphsetCache[i].next;
628         glyphsetCache[i].next = mru;
629         mru = i;
630       }
631       TRACE("found font in cache %d\n", i);
632       return i;
633     }
634     prev_i = i;
635   }
636   TRACE("font not in cache\n");
637   return -1;
638 }
639
640 static void FreeEntry(int entry)
641 {
642     int format;
643
644     for(format = 0; format < AA_MAXVALUE; format++) {
645         gsCacheEntryFormat * formatEntry;
646
647         if( !glyphsetCache[entry].format[format] )
648             continue;
649
650         formatEntry = glyphsetCache[entry].format[format];
651
652         if(formatEntry->glyphset) {
653             pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
654             formatEntry->glyphset = 0;
655         }
656         if(formatEntry->nrealized) {
657             HeapFree(GetProcessHeap(), 0, formatEntry->realized);
658             formatEntry->realized = NULL;
659             HeapFree(GetProcessHeap(), 0, formatEntry->gis);
660             formatEntry->gis = NULL;
661             formatEntry->nrealized = 0;
662         }
663
664         HeapFree(GetProcessHeap(), 0, formatEntry);
665         glyphsetCache[entry].format[format] = NULL;
666     }
667 }
668
669 static int AllocEntry(void)
670 {
671   int best = -1, prev_best = -1, i, prev_i = -1;
672
673   if(lastfree >= 0) {
674     assert(glyphsetCache[lastfree].count == -1);
675     glyphsetCache[lastfree].count = 1;
676     best = lastfree;
677     lastfree = glyphsetCache[lastfree].next;
678     assert(best != mru);
679     glyphsetCache[best].next = mru;
680     mru = best;
681
682     TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
683     return mru;
684   }
685
686   for(i = mru; i >= 0; i = glyphsetCache[i].next) {
687     if(glyphsetCache[i].count == 0) {
688       best = i;
689       prev_best = prev_i;
690     }
691     prev_i = i;
692   }
693
694   if(best >= 0) {
695     TRACE("freeing unused glyphset at cache %d\n", best);
696     FreeEntry(best);
697     glyphsetCache[best].count = 1;
698     if(prev_best >= 0) {
699       glyphsetCache[prev_best].next = glyphsetCache[best].next;
700       glyphsetCache[best].next = mru;
701       mru = best;
702     } else {
703       assert(mru == best);
704     }
705     return mru;
706   }
707
708   TRACE("Growing cache\n");
709   
710   if (glyphsetCache)
711     glyphsetCache = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
712                               glyphsetCache,
713                               (glyphsetCacheSize + INIT_CACHE_SIZE)
714                               * sizeof(*glyphsetCache));
715   else
716     glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
717                               (glyphsetCacheSize + INIT_CACHE_SIZE)
718                               * sizeof(*glyphsetCache));
719
720   for(best = i = glyphsetCacheSize; i < glyphsetCacheSize + INIT_CACHE_SIZE;
721       i++) {
722     glyphsetCache[i].next = i + 1;
723     glyphsetCache[i].count = -1;
724   }
725   glyphsetCache[i-1].next = -1;
726   glyphsetCacheSize += INIT_CACHE_SIZE;
727
728   lastfree = glyphsetCache[best].next;
729   glyphsetCache[best].count = 1;
730   glyphsetCache[best].next = mru;
731   mru = best;
732   TRACE("new free cache slot at %d\n", mru);
733   return mru;
734 }
735
736 static int GetCacheEntry( LFANDSIZE *plfsz )
737 {
738     int ret;
739     int format;
740     gsCacheEntry *entry;
741
742     if((ret = LookupEntry(plfsz)) != -1) return ret;
743
744     ret = AllocEntry();
745     entry = glyphsetCache + ret;
746     entry->lfsz = *plfsz;
747     for( format = 0; format < AA_MAXVALUE; format++ ) {
748         assert( !entry->format[format] );
749     }
750
751     return ret;
752 }
753
754 static void dec_ref_cache(int index)
755 {
756     assert(index >= 0);
757     TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
758     assert(glyphsetCache[index].count > 0);
759     glyphsetCache[index].count--;
760 }
761
762 static void lfsz_calc_hash(LFANDSIZE *plfsz)
763 {
764   DWORD hash = 0, *ptr, two_chars;
765   WORD *pwc;
766   int i;
767
768   hash ^= plfsz->devsize.cx;
769   hash ^= plfsz->devsize.cy;
770   for(i = 0, ptr = (DWORD*)&plfsz->xform; i < sizeof(XFORM)/sizeof(DWORD); i++, ptr++)
771     hash ^= *ptr;
772   for(i = 0, ptr = (DWORD*)&plfsz->lf; i < 7; i++, ptr++)
773     hash ^= *ptr;
774   for(i = 0, ptr = (DWORD*)plfsz->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
775     two_chars = *ptr;
776     pwc = (WCHAR *)&two_chars;
777     if(!*pwc) break;
778     *pwc = toupperW(*pwc);
779     pwc++;
780     *pwc = toupperW(*pwc);
781     hash ^= two_chars;
782     if(!*pwc) break;
783   }
784   plfsz->hash = hash;
785   return;
786 }
787
788 static AA_Type aa_type_from_flags( UINT aa_flags )
789 {
790     switch (aa_flags & 0x7f)
791     {
792     case GGO_BITMAP:
793         return AA_None;
794     case WINE_GGO_GRAY16_BITMAP:
795         return AA_Grey;
796     case WINE_GGO_HRGB_BITMAP:
797         return AA_RGB;
798     case WINE_GGO_HBGR_BITMAP:
799         return AA_BGR;
800     case WINE_GGO_VRGB_BITMAP:
801         return AA_VRGB;
802     case WINE_GGO_VBGR_BITMAP:
803         return AA_VBGR;
804     default:
805         FIXME( "unknown flags %x\n", aa_flags );
806         return AA_None;
807     }
808 }
809
810 static UINT get_xft_aa_flags( const LOGFONTW *lf )
811 {
812     char *value;
813     UINT ret = 0;
814
815     switch (lf->lfQuality)
816     {
817     case NONANTIALIASED_QUALITY:
818     case ANTIALIASED_QUALITY:
819         break;
820     default:
821         if (!(value = XGetDefault( gdi_display, "Xft", "antialias" ))) break;
822         TRACE( "got antialias '%s'\n", value );
823         if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
824             value[0] == '0' || !strcasecmp( value, "off" ))
825         {
826             ret = GGO_BITMAP;
827             break;
828         }
829         ret = GGO_GRAY4_BITMAP;
830         /* fall through */
831     case CLEARTYPE_QUALITY:
832     case CLEARTYPE_NATURAL_QUALITY:
833         if (!(value = XGetDefault( gdi_display, "Xft", "rgba" ))) break;
834         TRACE( "got rgba '%s'\n", value );
835         if (!strcmp( value, "rgb" )) ret = WINE_GGO_HRGB_BITMAP;
836         else if (!strcmp( value, "bgr" )) ret = WINE_GGO_HBGR_BITMAP;
837         else if (!strcmp( value, "vrgb" )) ret = WINE_GGO_VRGB_BITMAP;
838         else if (!strcmp( value, "vbgr" )) ret = WINE_GGO_VBGR_BITMAP;
839         else if (!strcmp( value, "none" )) ret = GGO_GRAY4_BITMAP;
840         break;
841     }
842     return ret;
843 }
844
845 /**********************************************************************
846  *           xrenderdrv_SelectFont
847  */
848 static HFONT xrenderdrv_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
849 {
850     LFANDSIZE lfsz;
851     struct xrender_physdev *physdev = get_xrender_dev( dev );
852     PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont );
853     HFONT ret;
854
855     GetObjectW( hfont, sizeof(lfsz.lf), &lfsz.lf );
856     if (!*aa_flags) *aa_flags = get_xft_aa_flags( &lfsz.lf );
857
858     ret = next->funcs->pSelectFont( next, hfont, aa_flags );
859     if (!ret) return 0;
860
861     switch (*aa_flags)
862     {
863     case GGO_GRAY2_BITMAP:
864     case GGO_GRAY4_BITMAP:
865     case GGO_GRAY8_BITMAP:
866         physdev->aa_flags = WINE_GGO_GRAY16_BITMAP;
867         break;
868     case 0:
869         physdev->aa_flags = GGO_BITMAP;
870         break;
871     default:
872         physdev->aa_flags = *aa_flags;
873         break;
874     }
875
876     TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
877           lfsz.lf.lfHeight, lfsz.lf.lfWidth, lfsz.lf.lfWeight,
878           lfsz.lf.lfItalic, lfsz.lf.lfCharSet, debugstr_w(lfsz.lf.lfFaceName));
879     lfsz.lf.lfWidth = abs( lfsz.lf.lfWidth );
880     lfsz.devsize.cx = X11DRV_XWStoDS( dev->hdc, lfsz.lf.lfWidth );
881     lfsz.devsize.cy = X11DRV_YWStoDS( dev->hdc, lfsz.lf.lfHeight );
882
883     GetTransform( dev->hdc, 0x204, &lfsz.xform );
884     TRACE("font transform %f %f %f %f\n", lfsz.xform.eM11, lfsz.xform.eM12,
885           lfsz.xform.eM21, lfsz.xform.eM22);
886
887     if (GetGraphicsMode( dev->hdc ) == GM_COMPATIBLE && lfsz.xform.eM11 * lfsz.xform.eM22 < 0)
888         lfsz.lf.lfOrientation = -lfsz.lf.lfOrientation;
889
890     /* Not used fields, would break hashing */
891     lfsz.xform.eDx = lfsz.xform.eDy = 0;
892
893     lfsz_calc_hash(&lfsz);
894
895     EnterCriticalSection(&xrender_cs);
896     if (physdev->cache_index != -1)
897         dec_ref_cache( physdev->cache_index );
898     physdev->cache_index = GetCacheEntry( &lfsz );
899     LeaveCriticalSection(&xrender_cs);
900     return ret;
901 }
902
903 static BOOL create_xrender_dc( PHYSDEV *pdev, enum wxr_format format )
904 {
905     X11DRV_PDEVICE *x11dev = get_x11drv_dev( *pdev );
906     struct xrender_physdev *physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) );
907
908     if (!physdev) return FALSE;
909     physdev->x11dev = x11dev;
910     physdev->cache_index = -1;
911     physdev->format = format;
912     physdev->pict_format = pict_formats[format];
913     push_dc_driver( pdev, &physdev->dev, &xrender_funcs );
914     return TRUE;
915 }
916
917 /* store the color mask data in the bitmap info structure */
918 static void set_color_info( XRenderPictFormat *format, BITMAPINFO *info )
919 {
920     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
921
922     info->bmiHeader.biPlanes      = 1;
923     info->bmiHeader.biBitCount    = pixmap_formats[format->depth]->bits_per_pixel;
924     info->bmiHeader.biCompression = BI_RGB;
925     info->bmiHeader.biClrUsed     = 0;
926
927     switch (info->bmiHeader.biBitCount)
928     {
929     case 16:
930         colors[0] = format->direct.redMask   << format->direct.red;
931         colors[1] = format->direct.greenMask << format->direct.green;
932         colors[2] = format->direct.blueMask  << format->direct.blue;
933         info->bmiHeader.biCompression = BI_BITFIELDS;
934         break;
935     case 32:
936         colors[0] = format->direct.redMask   << format->direct.red;
937         colors[1] = format->direct.greenMask << format->direct.green;
938         colors[2] = format->direct.blueMask  << format->direct.blue;
939         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
940             info->bmiHeader.biCompression = BI_BITFIELDS;
941         break;
942     }
943 }
944
945
946 /**********************************************************************
947  *           xrenderdrv_CreateDC
948  */
949 static BOOL xrenderdrv_CreateDC( PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
950                                  LPCWSTR output, const DEVMODEW* initData )
951 {
952     return create_xrender_dc( pdev, default_format );
953 }
954
955 /**********************************************************************
956  *           xrenderdrv_CreateCompatibleDC
957  */
958 static BOOL xrenderdrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
959 {
960     if (orig)  /* chain to x11drv first */
961     {
962         orig = GET_NEXT_PHYSDEV( orig, pCreateCompatibleDC );
963         if (!orig->funcs->pCreateCompatibleDC( orig, pdev )) return FALSE;
964     }
965     /* otherwise we have been called by x11drv */
966
967     return create_xrender_dc( pdev, WXR_FORMAT_MONO );
968 }
969
970 /**********************************************************************
971  *           xrenderdrv_DeleteDC
972  */
973 static BOOL xrenderdrv_DeleteDC( PHYSDEV dev )
974 {
975     struct xrender_physdev *physdev = get_xrender_dev( dev );
976
977     free_xrender_picture( physdev );
978
979     EnterCriticalSection( &xrender_cs );
980     if (physdev->cache_index != -1) dec_ref_cache( physdev->cache_index );
981     LeaveCriticalSection( &xrender_cs );
982
983     HeapFree( GetProcessHeap(), 0, physdev );
984     return TRUE;
985 }
986
987 /**********************************************************************
988  *           xrenderdrv_ExtEscape
989  */
990 static INT xrenderdrv_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data,
991                                  INT out_count, LPVOID out_data )
992 {
993     struct xrender_physdev *physdev = get_xrender_dev( dev );
994
995     dev = GET_NEXT_PHYSDEV( dev, pExtEscape );
996
997     if (escape == X11DRV_ESCAPE && in_data && in_count >= sizeof(enum x11drv_escape_codes))
998     {
999         if (*(const enum x11drv_escape_codes *)in_data == X11DRV_SET_DRAWABLE)
1000         {
1001             BOOL ret = dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1002             if (ret) free_xrender_picture( physdev );  /* pict format doesn't change, only drawable */
1003             return ret;
1004         }
1005     }
1006     return dev->funcs->pExtEscape( dev, escape, in_count, in_data, out_count, out_data );
1007 }
1008
1009 /***********************************************************************
1010  *           xrenderdrv_SetDeviceClipping
1011  */
1012 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev, HRGN rgn )
1013 {
1014     struct xrender_physdev *physdev = get_xrender_dev( dev );
1015
1016     physdev->region = rgn;
1017     physdev->update_clip = TRUE;
1018
1019     dev = GET_NEXT_PHYSDEV( dev, pSetDeviceClipping );
1020     dev->funcs->pSetDeviceClipping( dev, rgn );
1021 }
1022
1023
1024 /************************************************************************
1025  *   UploadGlyph
1026  *
1027  * Helper to ExtTextOut.  Must be called inside xrender_cs
1028  */
1029 static void UploadGlyph(struct xrender_physdev *physDev, int glyph)
1030 {
1031     unsigned int buflen;
1032     char *buf;
1033     Glyph gid;
1034     GLYPHMETRICS gm;
1035     XGlyphInfo gi;
1036     gsCacheEntry *entry = glyphsetCache + physDev->cache_index;
1037     gsCacheEntryFormat *formatEntry;
1038     UINT ggo_format = GGO_GLYPH_INDEX | physDev->aa_flags;
1039     AA_Type format = aa_type_from_flags( physDev->aa_flags );
1040     enum wxr_format wxr_format;
1041     static const char zero[4];
1042     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
1043
1044     buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1045     if(buflen == GDI_ERROR) {
1046         if(format != AA_None) {
1047             format = AA_None;
1048             physDev->aa_flags = GGO_BITMAP;
1049             ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
1050             buflen = GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, 0, NULL, &identity);
1051         }
1052         if(buflen == GDI_ERROR) {
1053             WARN("GetGlyphOutlineW failed using default glyph\n");
1054             buflen = GetGlyphOutlineW(physDev->dev.hdc, 0, ggo_format, &gm, 0, NULL, &identity);
1055             if(buflen == GDI_ERROR) {
1056                 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1057                 buflen = GetGlyphOutlineW(physDev->dev.hdc, 0x20, ggo_format, &gm, 0, NULL, &identity);
1058                 if(buflen == GDI_ERROR) {
1059                     ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1060                     return;
1061                 }
1062             }
1063         }
1064         TRACE("Turning off antialiasing for this monochrome font\n");
1065     }
1066
1067     /* If there is nothing for the current type, we create the entry. */
1068     if( !entry->format[format] ) {
1069         entry->format[format] = HeapAlloc(GetProcessHeap(),
1070                                           HEAP_ZERO_MEMORY,
1071                                           sizeof(gsCacheEntryFormat));
1072     }
1073     formatEntry = entry->format[format];
1074
1075     if(formatEntry->nrealized <= glyph) {
1076         formatEntry->nrealized = (glyph / 128 + 1) * 128;
1077
1078         if (formatEntry->realized)
1079             formatEntry->realized = HeapReAlloc(GetProcessHeap(),
1080                                       HEAP_ZERO_MEMORY,
1081                                       formatEntry->realized,
1082                                       formatEntry->nrealized * sizeof(BOOL));
1083         else
1084             formatEntry->realized = HeapAlloc(GetProcessHeap(),
1085                                       HEAP_ZERO_MEMORY,
1086                                       formatEntry->nrealized * sizeof(BOOL));
1087
1088         if (formatEntry->gis)
1089             formatEntry->gis = HeapReAlloc(GetProcessHeap(),
1090                                    HEAP_ZERO_MEMORY,
1091                                    formatEntry->gis,
1092                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1093         else
1094             formatEntry->gis = HeapAlloc(GetProcessHeap(),
1095                                    HEAP_ZERO_MEMORY,
1096                                    formatEntry->nrealized * sizeof(formatEntry->gis[0]));
1097     }
1098
1099
1100     if(formatEntry->glyphset == 0) {
1101         switch(format) {
1102             case AA_Grey:
1103                 wxr_format = WXR_FORMAT_GRAY;
1104                 break;
1105
1106             case AA_RGB:
1107             case AA_BGR:
1108             case AA_VRGB:
1109             case AA_VBGR:
1110                 wxr_format = WXR_FORMAT_A8R8G8B8;
1111                 break;
1112
1113             default:
1114                 ERR("aa = %d - not implemented\n", format);
1115                 /* fall through */
1116             case AA_None:
1117                 wxr_format = WXR_FORMAT_MONO;
1118                 break;
1119         }
1120
1121         formatEntry->font_format = pict_formats[wxr_format];
1122         formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format);
1123     }
1124
1125
1126     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
1127     GetGlyphOutlineW(physDev->dev.hdc, glyph, ggo_format, &gm, buflen, buf, &identity);
1128     formatEntry->realized[glyph] = TRUE;
1129
1130     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1131           buflen,
1132           gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY,
1133           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1134
1135     gi.width = gm.gmBlackBoxX;
1136     gi.height = gm.gmBlackBoxY;
1137     gi.x = -gm.gmptGlyphOrigin.x;
1138     gi.y = gm.gmptGlyphOrigin.y;
1139     gi.xOff = gm.gmCellIncX;
1140     gi.yOff = gm.gmCellIncY;
1141
1142     if(TRACE_ON(xrender)) {
1143         int pitch, i, j;
1144         char output[300];
1145         unsigned char *line;
1146
1147         if(format == AA_None) {
1148             pitch = ((gi.width + 31) / 32) * 4;
1149             for(i = 0; i < gi.height; i++) {
1150                 line = (unsigned char*) buf + i * pitch;
1151                 output[0] = '\0';
1152                 for(j = 0; j < pitch * 8; j++) {
1153                     strcat(output, (line[j / 8] & (1 << (7 - (j % 8)))) ? "#" : " ");
1154                 }
1155                 TRACE("%s\n", output);
1156             }
1157         } else {
1158             static const char blks[] = " .:;!o*#";
1159             char str[2];
1160
1161             str[1] = '\0';
1162             pitch = ((gi.width + 3) / 4) * 4;
1163             for(i = 0; i < gi.height; i++) {
1164                 line = (unsigned char*) buf + i * pitch;
1165                 output[0] = '\0';
1166                 for(j = 0; j < pitch; j++) {
1167                     str[0] = blks[line[j] >> 5];
1168                     strcat(output, str);
1169                 }
1170                 TRACE("%s\n", output);
1171             }
1172         }
1173     }
1174
1175
1176     if(formatEntry->glyphset) {
1177         if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
1178             unsigned char *byte = (unsigned char*) buf, c;
1179             int i = buflen;
1180
1181             while(i--) {
1182                 c = *byte;
1183
1184                 /* magic to flip bit order */
1185                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1186                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1187                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1188
1189                 *byte++ = c;
1190             }
1191         }
1192         else if ( format != AA_Grey &&
1193                   ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
1194         {
1195             unsigned int i, *data = (unsigned int *)buf;
1196             for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
1197         }
1198         gid = glyph;
1199
1200         /*
1201           XRenderCompositeText seems to ignore 0x0 glyphs when
1202           AA_None, which means we lose the advance width of glyphs
1203           like the space.  We'll pretend that such glyphs are 1x1
1204           bitmaps.
1205         */
1206
1207         if(buflen == 0)
1208             gi.width = gi.height = 1;
1209
1210         pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
1211                           buflen ? buf : zero, buflen ? buflen : sizeof(zero));
1212     }
1213
1214     HeapFree(GetProcessHeap(), 0, buf);
1215     formatEntry->gis[glyph] = gi;
1216 }
1217
1218 /*************************************************************
1219  *                 get_tile_pict
1220  *
1221  * Returns an appropriate Picture for tiling the text colour.
1222  * Call and use result within the xrender_cs
1223  */
1224 static Picture get_tile_pict( enum wxr_format wxr_format, const XRenderColor *color)
1225 {
1226     static struct
1227     {
1228         Pixmap xpm;
1229         Picture pict;
1230         XRenderColor current_color;
1231     } tiles[WXR_NB_FORMATS], *tile;
1232
1233     tile = &tiles[wxr_format];
1234
1235     if(!tile->xpm)
1236     {
1237         XRenderPictureAttributes pa;
1238         XRenderPictFormat *pict_format = pict_formats[wxr_format];
1239
1240         tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, pict_format->depth);
1241
1242         pa.repeat = RepeatNormal;
1243         tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, pict_format, CPRepeat, &pa);
1244
1245         /* init current_color to something different from text_pixel */
1246         tile->current_color = *color;
1247         tile->current_color.red ^= 0xffff;
1248
1249         if (wxr_format == WXR_FORMAT_MONO)
1250         {
1251             /* for a 1bpp bitmap we always need a 1 in the tile */
1252             XRenderColor col;
1253             col.red = col.green = col.blue = 0;
1254             col.alpha = 0xffff;
1255             pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, &col, 0, 0, 1, 1);
1256         }
1257     }
1258
1259     if (memcmp( color, &tile->current_color, sizeof(*color) ) && wxr_format != WXR_FORMAT_MONO)
1260     {
1261         pXRenderFillRectangle(gdi_display, PictOpSrc, tile->pict, color, 0, 0, 1, 1);
1262         tile->current_color = *color;
1263     }
1264     return tile->pict;
1265 }
1266
1267 /*************************************************************
1268  *                 get_mask_pict
1269  *
1270  * Returns an appropriate Picture for masking with the specified alpha.
1271  * Call and use result within the xrender_cs
1272  */
1273 static Picture get_mask_pict( int alpha )
1274 {
1275     static Pixmap pixmap;
1276     static Picture pict;
1277     static int current_alpha;
1278
1279     if (alpha == 0xffff) return 0;  /* don't need a mask for alpha==1.0 */
1280
1281     if (!pixmap)
1282     {
1283         XRenderPictureAttributes pa;
1284
1285         pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 32 );
1286         pa.repeat = RepeatNormal;
1287         pict = pXRenderCreatePicture( gdi_display, pixmap,
1288                                       pict_formats[WXR_FORMAT_A8R8G8B8], CPRepeat, &pa );
1289         current_alpha = -1;
1290     }
1291
1292     if (alpha != current_alpha)
1293     {
1294         XRenderColor col;
1295         col.red = col.green = col.blue = 0;
1296         col.alpha = current_alpha = alpha;
1297         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &col, 0, 0, 1, 1 );
1298     }
1299     return pict;
1300 }
1301
1302 /***********************************************************************
1303  *           xrenderdrv_ExtTextOut
1304  */
1305 static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
1306                                    const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx )
1307 {
1308     struct xrender_physdev *physdev = get_xrender_dev( dev );
1309     gsCacheEntry *entry;
1310     gsCacheEntryFormat *formatEntry;
1311     unsigned int idx;
1312     Picture pict, tile_pict = 0;
1313     XGlyphElt16 *elts;
1314     POINT offset, desired, current;
1315     int render_op = PictOpOver;
1316     XRenderColor col;
1317     RECT rect, bounds;
1318
1319     get_xrender_color( physdev, GetTextColor( physdev->dev.hdc ), &col );
1320     pict = get_xrender_picture( physdev, 0, (flags & ETO_CLIPPED) ? lprect : NULL );
1321
1322     if(flags & ETO_OPAQUE)
1323     {
1324         XRenderColor bg;
1325
1326         if (physdev->format == WXR_FORMAT_MONO)
1327             /* use the inverse of the text color */
1328             bg.red = bg.green = bg.blue = bg.alpha = ~col.alpha;
1329         else
1330             get_xrender_color( physdev, GetBkColor( physdev->dev.hdc ), &bg );
1331
1332         set_xrender_transformation( pict, 1, 1, 0, 0 );
1333         pXRenderFillRectangle( gdi_display, PictOpSrc, pict, &bg,
1334                                physdev->x11dev->dc_rect.left + lprect->left,
1335                                physdev->x11dev->dc_rect.top + lprect->top,
1336                                lprect->right - lprect->left,
1337                                lprect->bottom - lprect->top );
1338         add_device_bounds( physdev->x11dev, lprect );
1339     }
1340
1341     if(count == 0) return TRUE;
1342
1343     EnterCriticalSection(&xrender_cs);
1344
1345     entry = glyphsetCache + physdev->cache_index;
1346     formatEntry = entry->format[aa_type_from_flags( physdev->aa_flags )];
1347
1348     for(idx = 0; idx < count; idx++) {
1349         if( !formatEntry ) {
1350             UploadGlyph(physdev, wstr[idx]);
1351             /* re-evaluate format entry since aa_flags may have changed */
1352             formatEntry = entry->format[aa_type_from_flags( physdev->aa_flags )];
1353         } else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
1354             UploadGlyph(physdev, wstr[idx]);
1355         }
1356     }
1357     if (!formatEntry)
1358     {
1359         WARN("could not upload requested glyphs\n");
1360         LeaveCriticalSection(&xrender_cs);
1361         return FALSE;
1362     }
1363
1364     TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr,count),
1365           physdev->x11dev->dc_rect.left + x, physdev->x11dev->dc_rect.top + y);
1366
1367     elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
1368
1369     /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1370        So we pass zeros to the function and move to our starting position using the first
1371        element of the elts array. */
1372
1373     desired.x = physdev->x11dev->dc_rect.left + x;
1374     desired.y = physdev->x11dev->dc_rect.top + y;
1375     offset.x = offset.y = 0;
1376     current.x = current.y = 0;
1377
1378     tile_pict = get_tile_pict(physdev->format, &col);
1379
1380     /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1381      */
1382     if (physdev->format == WXR_FORMAT_MONO && col.red == 0 && col.green == 0 && col.blue == 0)
1383         render_op = PictOpOutReverse; /* This gives us 'black' text */
1384
1385     reset_bounds( &bounds );
1386     for(idx = 0; idx < count; idx++)
1387     {
1388         elts[idx].glyphset = formatEntry->glyphset;
1389         elts[idx].chars = wstr + idx;
1390         elts[idx].nchars = 1;
1391         elts[idx].xOff = desired.x - current.x;
1392         elts[idx].yOff = desired.y - current.y;
1393
1394         current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
1395         current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
1396
1397         rect.left   = desired.x - physdev->x11dev->dc_rect.left - formatEntry->gis[wstr[idx]].x;
1398         rect.top    = desired.y - physdev->x11dev->dc_rect.top - formatEntry->gis[wstr[idx]].y;
1399         rect.right  = rect.left + formatEntry->gis[wstr[idx]].width;
1400         rect.bottom = rect.top  + formatEntry->gis[wstr[idx]].height;
1401         add_bounds_rect( &bounds, &rect );
1402
1403         if(!lpDx)
1404         {
1405             desired.x += formatEntry->gis[wstr[idx]].xOff;
1406             desired.y += formatEntry->gis[wstr[idx]].yOff;
1407         }
1408         else
1409         {
1410             if(flags & ETO_PDY)
1411             {
1412                 offset.x += lpDx[idx * 2];
1413                 offset.y += lpDx[idx * 2 + 1];
1414             }
1415             else
1416                 offset.x += lpDx[idx];
1417             desired.x = physdev->x11dev->dc_rect.left + x + offset.x;
1418             desired.y = physdev->x11dev->dc_rect.top  + y + offset.y;
1419         }
1420     }
1421
1422     /* Make sure we don't have any transforms set from a previous call */
1423     set_xrender_transformation(pict, 1, 1, 0, 0);
1424     pXRenderCompositeText16(gdi_display, render_op,
1425                             tile_pict,
1426                             pict,
1427                             formatEntry->font_format,
1428                             0, 0, 0, 0, elts, count);
1429     HeapFree(GetProcessHeap(), 0, elts);
1430
1431     LeaveCriticalSection(&xrender_cs);
1432     add_device_bounds( physdev->x11dev, &bounds );
1433     return TRUE;
1434 }
1435
1436 /* multiply the alpha channel of a picture */
1437 static void multiply_alpha( Picture pict, XRenderPictFormat *format, int alpha,
1438                             int x, int y, int width, int height )
1439 {
1440     XRenderPictureAttributes pa;
1441     Pixmap src_pixmap, mask_pixmap;
1442     Picture src_pict, mask_pict;
1443     XRenderColor color;
1444
1445     src_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
1446     mask_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth );
1447     pa.repeat = RepeatNormal;
1448     src_pict = pXRenderCreatePicture( gdi_display, src_pixmap, format, CPRepeat, &pa );
1449     pa.component_alpha = True;
1450     mask_pict = pXRenderCreatePicture( gdi_display, mask_pixmap, format, CPRepeat|CPComponentAlpha, &pa );
1451     color.red = color.green = color.blue = color.alpha = 0xffff;
1452     pXRenderFillRectangle( gdi_display, PictOpSrc, src_pict, &color, 0, 0, 1, 1 );
1453     color.alpha = alpha;
1454     pXRenderFillRectangle( gdi_display, PictOpSrc, mask_pict, &color, 0, 0, 1, 1 );
1455     pXRenderComposite( gdi_display, PictOpInReverse, src_pict, mask_pict, pict,
1456                        0, 0, 0, 0, x, y, width, height );
1457     pXRenderFreePicture( gdi_display, src_pict );
1458     pXRenderFreePicture( gdi_display, mask_pict );
1459     XFreePixmap( gdi_display, src_pixmap );
1460     XFreePixmap( gdi_display, mask_pixmap );
1461 }
1462
1463 /* Helper function for (stretched) blitting using xrender */
1464 static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict,
1465                           int x_src, int y_src, int width_src, int height_src,
1466                           int x_dst, int y_dst, int width_dst, int height_dst,
1467                           double xscale, double yscale )
1468 {
1469     int x_offset, y_offset;
1470
1471     if (width_src < 0)
1472     {
1473         x_src += width_src + 1;
1474         width_src = -width_src;
1475     }
1476     if (height_src < 0)
1477     {
1478         y_src += height_src + 1;
1479         height_src = -height_src;
1480     }
1481     if (width_dst < 0)
1482     {
1483         x_dst += width_dst + 1;
1484         width_dst = -width_dst;
1485     }
1486     if (height_dst < 0)
1487     {
1488         y_dst += height_dst + 1;
1489         height_dst = -height_dst;
1490     }
1491
1492     /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
1493      * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
1494      * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
1495     if(xscale != 1.0 || yscale != 1.0)
1496     {
1497         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1498          * in the wrong quadrant of the x-y plane.
1499          */
1500         x_offset = (xscale < 0) ? -width_dst : 0;
1501         y_offset = (yscale < 0) ? -height_dst : 0;
1502         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1503     }
1504     else
1505     {
1506         x_offset = x_src;
1507         y_offset = y_src;
1508         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1509     }
1510     pXRenderComposite( gdi_display, op, src_pict, mask_pict, dst_pict,
1511                        x_offset, y_offset, 0, 0, x_dst, y_dst, width_dst, height_dst );
1512 }
1513
1514 /* Helper function for (stretched) mono->color blitting using xrender */
1515 static void xrender_mono_blit( Picture src_pict, Picture dst_pict,
1516                                enum wxr_format dst_format, XRenderColor *fg, XRenderColor *bg,
1517                                int x_src, int y_src, int width_src, int height_src,
1518                                int x_dst, int y_dst, int width_dst, int height_dst,
1519                                double xscale, double yscale )
1520 {
1521     Picture tile_pict;
1522     int x_offset, y_offset;
1523     XRenderColor color;
1524
1525     if (width_src < 0)
1526     {
1527         x_src += width_src + 1;
1528         width_src = -width_src;
1529     }
1530     if (height_src < 0)
1531     {
1532         y_src += height_src + 1;
1533         height_src = -height_src;
1534     }
1535     if (width_dst < 0)
1536     {
1537         x_dst += width_dst + 1;
1538         width_dst = -width_dst;
1539     }
1540     if (height_dst < 0)
1541     {
1542         y_dst += height_dst + 1;
1543         height_dst = -height_dst;
1544     }
1545
1546     /* When doing a mono->color blit, the source data is used as mask, and the source picture
1547      * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
1548      * the tile data.
1549      */
1550     EnterCriticalSection( &xrender_cs );
1551     color = *bg;
1552     color.alpha = 0xffff;  /* tile pict needs 100% alpha */
1553     tile_pict = get_tile_pict( dst_format, &color );
1554
1555     pXRenderFillRectangle( gdi_display, PictOpSrc, dst_pict, fg, x_dst, y_dst, width_dst, height_dst );
1556
1557     if (xscale != 1.0 || yscale != 1.0)
1558     {
1559         /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1560          * in the wrong quadrant of the x-y plane.
1561          */
1562         x_offset = (xscale < 0) ? -width_dst : 0;
1563         y_offset = (yscale < 0) ? -height_dst : 0;
1564         set_xrender_transformation(src_pict, xscale, yscale, x_src, y_src);
1565     }
1566     else
1567     {
1568         x_offset = x_src;
1569         y_offset = y_src;
1570         set_xrender_transformation(src_pict, 1, 1, 0, 0);
1571     }
1572     pXRenderComposite(gdi_display, PictOpOver, tile_pict, src_pict, dst_pict,
1573                       0, 0, x_offset, y_offset, x_dst, y_dst, width_dst, height_dst );
1574     LeaveCriticalSection( &xrender_cs );
1575
1576     /* force the alpha channel for background pixels, it has been set to 100% by the tile */
1577     if (bg->alpha != 0xffff && (dst_format == WXR_FORMAT_A8R8G8B8 || dst_format == WXR_FORMAT_B8G8R8A8))
1578         multiply_alpha( dst_pict, pict_formats[dst_format], bg->alpha,
1579                         x_dst, y_dst, width_dst, height_dst );
1580 }
1581
1582 /* create a pixmap and render picture for an image */
1583 static DWORD create_image_pixmap( BITMAPINFO *info, const struct gdi_image_bits *bits,
1584                                   struct bitblt_coords *src, enum wxr_format format,
1585                                   Pixmap *pixmap, Picture *pict, BOOL *use_repeat )
1586 {
1587     DWORD ret;
1588     int width = src->visrect.right - src->visrect.left;
1589     int height = src->visrect.bottom - src->visrect.top;
1590     int depth = pict_formats[format]->depth;
1591     struct gdi_image_bits dst_bits;
1592     XRenderPictureAttributes pa;
1593     GC gc;
1594     XImage *image;
1595
1596     image = XCreateImage( gdi_display, default_visual.visual, depth, ZPixmap, 0, NULL,
1597                           info->bmiHeader.biWidth, height, 32, 0 );
1598     if (!image) return ERROR_OUTOFMEMORY;
1599
1600     ret = copy_image_bits( info, (format == WXR_FORMAT_R8G8B8), image, bits, &dst_bits, src, NULL, ~0u );
1601     if (ret) return ret;
1602
1603     image->data = dst_bits.ptr;
1604
1605     *use_repeat = (width == 1 && height == 1);
1606     pa.repeat = *use_repeat ? RepeatNormal : RepeatNone;
1607
1608     *pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1609     gc = XCreateGC( gdi_display, *pixmap, 0, NULL );
1610     XPutImage( gdi_display, *pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1611     *pict = pXRenderCreatePicture( gdi_display, *pixmap, pict_formats[format], CPRepeat, &pa );
1612     XFreeGC( gdi_display, gc );
1613
1614     /* make coordinates relative to the pixmap */
1615     src->x -= src->visrect.left;
1616     src->y -= src->visrect.top;
1617     OffsetRect( &src->visrect, -src->visrect.left, -src->visrect.top );
1618
1619     image->data = NULL;
1620     XDestroyImage( image );
1621     if (dst_bits.free) dst_bits.free( &dst_bits );
1622     return ret;
1623 }
1624
1625 static void xrender_stretch_blit( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,
1626                                   Drawable drawable, const struct bitblt_coords *src,
1627                                   const struct bitblt_coords *dst )
1628 {
1629     int x_dst, y_dst;
1630     Picture src_pict = 0, dst_pict, mask_pict = 0;
1631     double xscale = src->width / (double)dst->width;
1632     double yscale = src->height / (double)dst->height;
1633
1634     if (drawable)  /* using an intermediate pixmap */
1635     {
1636         x_dst = dst->x;
1637         y_dst = dst->y;
1638         dst_pict = pXRenderCreatePicture( gdi_display, drawable, physdev_dst->pict_format, 0, NULL );
1639     }
1640     else
1641     {
1642         x_dst = physdev_dst->x11dev->dc_rect.left + dst->x;
1643         y_dst = physdev_dst->x11dev->dc_rect.top + dst->y;
1644         dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
1645     }
1646
1647     src_pict = get_xrender_picture_source( physdev_src, FALSE );
1648
1649     /* mono -> color */
1650     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
1651     {
1652         XRenderColor fg, bg;
1653
1654         get_xrender_color( physdev_dst, GetTextColor( physdev_dst->dev.hdc ), &fg );
1655         get_xrender_color( physdev_dst, GetBkColor( physdev_dst->dev.hdc ), &bg );
1656         fg.alpha = bg.alpha = 0;
1657
1658         xrender_mono_blit( src_pict, dst_pict, physdev_dst->format, &fg, &bg,
1659                            physdev_src->x11dev->dc_rect.left + src->x,
1660                            physdev_src->x11dev->dc_rect.top + src->y,
1661                            src->width, src->height, x_dst, y_dst, dst->width, dst->height, xscale, yscale );
1662     }
1663     else /* color -> color (can be at different depths) or mono -> mono */
1664     {
1665         if (physdev_dst->pict_format->depth == 32 && physdev_src->pict_format->depth < 32)
1666             mask_pict = get_no_alpha_mask();
1667
1668         xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict,
1669                       physdev_src->x11dev->dc_rect.left + src->x,
1670                       physdev_src->x11dev->dc_rect.top + src->y,
1671                       src->width, src->height, x_dst, y_dst, dst->width, dst->height, xscale, yscale );
1672     }
1673
1674     if (drawable) pXRenderFreePicture( gdi_display, dst_pict );
1675 }
1676
1677
1678 static void xrender_put_image( Pixmap src_pixmap, Picture src_pict, Picture mask_pict, HRGN clip,
1679                                XRenderPictFormat *dst_format, struct xrender_physdev *physdev,
1680                                Drawable drawable, struct bitblt_coords *src,
1681                                struct bitblt_coords *dst, BOOL use_repeat )
1682 {
1683     int x_dst, y_dst;
1684     Picture dst_pict;
1685     double xscale, yscale;
1686
1687     if (drawable)  /* using an intermediate pixmap */
1688     {
1689         RGNDATA *clip_data = NULL;
1690
1691         if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1692         x_dst = dst->x;
1693         y_dst = dst->y;
1694         dst_pict = pXRenderCreatePicture( gdi_display, drawable, dst_format, 0, NULL );
1695         if (clip_data)
1696             pXRenderSetPictureClipRectangles( gdi_display, dst_pict, 0, 0,
1697                                               (XRectangle *)clip_data->Buffer, clip_data->rdh.nCount );
1698         HeapFree( GetProcessHeap(), 0, clip_data );
1699     }
1700     else
1701     {
1702         x_dst = physdev->x11dev->dc_rect.left + dst->x;
1703         y_dst = physdev->x11dev->dc_rect.top + dst->y;
1704         dst_pict = get_xrender_picture( physdev, clip, &dst->visrect );
1705     }
1706
1707     if (!use_repeat)
1708     {
1709         xscale = src->width / (double)dst->width;
1710         yscale = src->height / (double)dst->height;
1711     }
1712     else xscale = yscale = 1;  /* no scaling needed with a repeating source */
1713
1714     xrender_blit( PictOpSrc, src_pict, mask_pict, dst_pict, src->x, src->y, src->width, src->height,
1715                   x_dst, y_dst, dst->width, dst->height, xscale, yscale );
1716
1717     if (drawable) pXRenderFreePicture( gdi_display, dst_pict );
1718 }
1719
1720
1721 /***********************************************************************
1722  *           xrenderdrv_StretchBlt
1723  */
1724 static BOOL xrenderdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
1725                                    PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
1726 {
1727     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
1728     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
1729     BOOL stretch = (src->width != dst->width) || (src->height != dst->height);
1730
1731     if (src_dev->funcs != dst_dev->funcs)
1732     {
1733         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
1734         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
1735     }
1736
1737     /* XRender is of no use for color -> mono */
1738     if (physdev_dst->format == WXR_FORMAT_MONO && physdev_src->format != WXR_FORMAT_MONO)
1739         goto x11drv_fallback;
1740
1741     /* if not stretching, we only need to handle format conversion */
1742     if (!stretch && physdev_dst->format == physdev_src->format) goto x11drv_fallback;
1743
1744     if (rop != SRCCOPY)
1745     {
1746         GC tmpGC;
1747         Pixmap tmp_pixmap;
1748         struct bitblt_coords tmp;
1749
1750         /* make coordinates relative to tmp pixmap */
1751         tmp = *dst;
1752         tmp.x -= tmp.visrect.left;
1753         tmp.y -= tmp.visrect.top;
1754         OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
1755
1756         tmpGC = XCreateGC( gdi_display, physdev_dst->x11dev->drawable, 0, NULL );
1757         XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
1758         XSetGraphicsExposures( gdi_display, tmpGC, False );
1759         tmp_pixmap = XCreatePixmap( gdi_display, root_window, tmp.visrect.right - tmp.visrect.left,
1760                                     tmp.visrect.bottom - tmp.visrect.top, physdev_dst->pict_format->depth );
1761
1762         xrender_stretch_blit( physdev_src, physdev_dst, tmp_pixmap, src, &tmp );
1763         execute_rop( physdev_dst->x11dev, tmp_pixmap, tmpGC, &dst->visrect, rop );
1764
1765         XFreePixmap( gdi_display, tmp_pixmap );
1766         XFreeGC( gdi_display, tmpGC );
1767     }
1768     else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
1769
1770     add_device_bounds( physdev_dst->x11dev, &dst->visrect );
1771     return TRUE;
1772
1773 x11drv_fallback:
1774     return X11DRV_StretchBlt( &physdev_dst->x11dev->dev, dst, &physdev_src->x11dev->dev, src, rop );
1775 }
1776
1777
1778 /***********************************************************************
1779  *           xrenderdrv_PutImage
1780  */
1781 static DWORD xrenderdrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1782                                   const struct gdi_image_bits *bits, struct bitblt_coords *src,
1783                                   struct bitblt_coords *dst, DWORD rop )
1784 {
1785     struct xrender_physdev *physdev = get_xrender_dev( dev );
1786     DWORD ret;
1787     Pixmap tmp_pixmap;
1788     GC gc;
1789     enum wxr_format src_format, dst_format;
1790     XRenderPictFormat *pict_format;
1791     Pixmap src_pixmap;
1792     Picture src_pict, mask_pict = 0;
1793     BOOL use_repeat;
1794
1795     dst_format = physdev->format;
1796     src_format = get_xrender_format_from_bitmapinfo( info );
1797     if (!(pict_format = pict_formats[src_format])) goto update_format;
1798
1799     /* make sure we can create an image with the same bpp */
1800     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
1801         goto update_format;
1802
1803     /* mono <-> color conversions not supported */
1804     if ((src_format != dst_format) && (src_format == WXR_FORMAT_MONO || dst_format == WXR_FORMAT_MONO))
1805         goto x11drv_fallback;
1806
1807     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1808
1809     if (!has_alpha( src_format ) && has_alpha( dst_format )) mask_pict = get_no_alpha_mask();
1810
1811     ret = create_image_pixmap( info, bits, src, src_format, &src_pixmap, &src_pict, &use_repeat );
1812     if (!ret)
1813     {
1814         struct bitblt_coords tmp;
1815
1816         if (rop != SRCCOPY)
1817         {
1818             BOOL restore_region = add_extra_clipping_region( physdev->x11dev, clip );
1819
1820             /* make coordinates relative to tmp pixmap */
1821             tmp = *dst;
1822             tmp.x -= tmp.visrect.left;
1823             tmp.y -= tmp.visrect.top;
1824             OffsetRect( &tmp.visrect, -tmp.visrect.left, -tmp.visrect.top );
1825
1826             gc = XCreateGC( gdi_display, physdev->x11dev->drawable, 0, NULL );
1827             XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1828             XSetGraphicsExposures( gdi_display, gc, False );
1829             tmp_pixmap = XCreatePixmap( gdi_display, root_window,
1830                                         tmp.visrect.right - tmp.visrect.left,
1831                                         tmp.visrect.bottom - tmp.visrect.top,
1832                                         physdev->pict_format->depth );
1833
1834             xrender_put_image( src_pixmap, src_pict, mask_pict, NULL, physdev->pict_format,
1835                                NULL, tmp_pixmap, src, &tmp, use_repeat );
1836             execute_rop( physdev->x11dev, tmp_pixmap, gc, &dst->visrect, rop );
1837
1838             XFreePixmap( gdi_display, tmp_pixmap );
1839             XFreeGC( gdi_display, gc );
1840             if (restore_region) restore_clipping_region( physdev->x11dev );
1841         }
1842         else xrender_put_image( src_pixmap, src_pict, mask_pict, clip,
1843                                 physdev->pict_format, physdev, 0, src, dst, use_repeat );
1844
1845         add_device_bounds( physdev->x11dev, &dst->visrect );
1846
1847         pXRenderFreePicture( gdi_display, src_pict );
1848         XFreePixmap( gdi_display, src_pixmap );
1849     }
1850     return ret;
1851
1852 update_format:
1853     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1854     set_color_info( pict_formats[dst_format], info );
1855     return ERROR_BAD_FORMAT;
1856
1857 x11drv_fallback:
1858     dev = GET_NEXT_PHYSDEV( dev, pPutImage );
1859     return dev->funcs->pPutImage( dev, clip, info, bits, src, dst, rop );
1860 }
1861
1862
1863 /***********************************************************************
1864  *           xrenderdrv_BlendImage
1865  */
1866 static DWORD xrenderdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits,
1867                                     struct bitblt_coords *src, struct bitblt_coords *dst,
1868                                     BLENDFUNCTION func )
1869 {
1870     struct xrender_physdev *physdev = get_xrender_dev( dev );
1871     DWORD ret;
1872     enum wxr_format format;
1873     XRenderPictFormat *pict_format;
1874     Picture dst_pict, src_pict, mask_pict;
1875     Pixmap src_pixmap;
1876     BOOL use_repeat;
1877
1878     format = get_xrender_format_from_bitmapinfo( info );
1879     if (!(func.AlphaFormat & AC_SRC_ALPHA))
1880         format = get_format_without_alpha( format );
1881     else if (format != WXR_FORMAT_A8R8G8B8 || info->bmiHeader.biCompression != BI_RGB)
1882         return ERROR_INVALID_PARAMETER;
1883
1884     if (!(pict_format = pict_formats[format])) goto update_format;
1885
1886     /* make sure we can create an image with the same bpp */
1887     if (info->bmiHeader.biBitCount != pixmap_formats[pict_format->depth]->bits_per_pixel)
1888         goto update_format;
1889
1890     if (format == WXR_FORMAT_MONO && physdev->format != WXR_FORMAT_MONO)
1891         goto update_format;
1892
1893     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1894
1895     ret = create_image_pixmap( info, bits, src, format, &src_pixmap, &src_pict, &use_repeat );
1896     if (!ret)
1897     {
1898         double xscale, yscale;
1899
1900         if (!use_repeat)
1901         {
1902             xscale = src->width / (double)dst->width;
1903             yscale = src->height / (double)dst->height;
1904         }
1905         else xscale = yscale = 1;  /* no scaling needed with a repeating source */
1906
1907         dst_pict = get_xrender_picture( physdev, 0, &dst->visrect );
1908
1909         EnterCriticalSection( &xrender_cs );
1910         mask_pict = get_mask_pict( func.SourceConstantAlpha * 257 );
1911
1912         xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
1913                       src->x, src->y, src->width, src->height,
1914                       physdev->x11dev->dc_rect.left + dst->x,
1915                       physdev->x11dev->dc_rect.top + dst->y,
1916                       dst->width, dst->height, xscale, yscale );
1917
1918         pXRenderFreePicture( gdi_display, src_pict );
1919         XFreePixmap( gdi_display, src_pixmap );
1920
1921         LeaveCriticalSection( &xrender_cs );
1922         add_device_bounds( physdev->x11dev, &dst->visrect );
1923     }
1924     return ret;
1925
1926 update_format:
1927     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1928     set_color_info( physdev->pict_format, info );
1929     return ERROR_BAD_FORMAT;
1930 }
1931
1932
1933 /***********************************************************************
1934  *           xrenderdrv_AlphaBlend
1935  */
1936 static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
1937                                    PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
1938 {
1939     struct xrender_physdev *physdev_dst = get_xrender_dev( dst_dev );
1940     struct xrender_physdev *physdev_src = get_xrender_dev( src_dev );
1941     Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
1942     XRenderPictureAttributes pa;
1943     Pixmap tmp_pixmap = 0;
1944     double xscale, yscale;
1945
1946     if (src_dev->funcs != dst_dev->funcs)
1947     {
1948         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pAlphaBlend );
1949         return dst_dev->funcs->pAlphaBlend( dst_dev, dst, src_dev, src, blendfn );
1950     }
1951
1952     if ((blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->format != WXR_FORMAT_A8R8G8B8)
1953     {
1954         SetLastError( ERROR_INVALID_PARAMETER );
1955         return FALSE;
1956     }
1957
1958     dst_pict = get_xrender_picture( physdev_dst, 0, &dst->visrect );
1959
1960     xscale = src->width / (double)dst->width;
1961     yscale = src->height / (double)dst->height;
1962
1963     src_pict = get_xrender_picture_source( physdev_src, FALSE );
1964
1965     if (physdev_src->format == WXR_FORMAT_MONO && physdev_dst->format != WXR_FORMAT_MONO)
1966     {
1967         /* mono -> color blending needs an intermediate color pixmap */
1968         XRenderColor fg, bg;
1969         int width = src->visrect.right - src->visrect.left;
1970         int height = src->visrect.bottom - src->visrect.top;
1971
1972         /* blending doesn't use the destination DC colors */
1973         fg.red = fg.green = fg.blue = 0;
1974         bg.red = bg.green = bg.blue = 0xffff;
1975         fg.alpha = bg.alpha = 0xffff;
1976
1977         tmp_pixmap = XCreatePixmap( gdi_display, root_window, width, height,
1978                                     physdev_dst->pict_format->depth );
1979         tmp_pict = pXRenderCreatePicture( gdi_display, tmp_pixmap, physdev_dst->pict_format, 0, NULL );
1980
1981         xrender_mono_blit( src_pict, tmp_pict, physdev_dst->format, &fg, &bg,
1982                            src->visrect.left, src->visrect.top, width, height, 0, 0, width, height, 1, 1 );
1983     }
1984     else if (!(blendfn.AlphaFormat & AC_SRC_ALPHA) && physdev_src->pict_format)
1985     {
1986         /* we need a source picture with no alpha */
1987         enum wxr_format format = get_format_without_alpha( physdev_src->format );
1988         if (format != physdev_src->format)
1989         {
1990             pa.subwindow_mode = IncludeInferiors;
1991             tmp_pict = pXRenderCreatePicture( gdi_display, physdev_src->x11dev->drawable,
1992                                               pict_formats[format], CPSubwindowMode, &pa );
1993         }
1994     }
1995
1996     if (tmp_pict) src_pict = tmp_pict;
1997
1998     EnterCriticalSection( &xrender_cs );
1999     mask_pict = get_mask_pict( blendfn.SourceConstantAlpha * 257 );
2000
2001     xrender_blit( PictOpOver, src_pict, mask_pict, dst_pict,
2002                   physdev_src->x11dev->dc_rect.left + src->x,
2003                   physdev_src->x11dev->dc_rect.top + src->y,
2004                   src->width, src->height,
2005                   physdev_dst->x11dev->dc_rect.left + dst->x,
2006                   physdev_dst->x11dev->dc_rect.top + dst->y,
2007                   dst->width, dst->height, xscale, yscale );
2008
2009     if (tmp_pict) pXRenderFreePicture( gdi_display, tmp_pict );
2010     if (tmp_pixmap) XFreePixmap( gdi_display, tmp_pixmap );
2011
2012     LeaveCriticalSection( &xrender_cs );
2013     add_device_bounds( physdev_dst->x11dev, &dst->visrect );
2014     return TRUE;
2015 }
2016
2017 /***********************************************************************
2018  *           xrenderdrv_GradientFill
2019  */
2020 static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
2021                                      void * grad_array, ULONG ngrad, ULONG mode )
2022 {
2023 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
2024     static const XFixed stops[2] = { 0, 1 << 16 };
2025     struct xrender_physdev *physdev = get_xrender_dev( dev );
2026     XLinearGradient gradient;
2027     XRenderColor colors[2];
2028     Picture src_pict, dst_pict;
2029     unsigned int i;
2030     const GRADIENT_RECT *rect = grad_array;
2031     RECT rc;
2032     POINT pt[2];
2033
2034     if (!pXRenderCreateLinearGradient) goto fallback;
2035
2036     /* <= 16-bpp uses dithering */
2037     if (!physdev->pict_format || physdev->pict_format->depth <= 16) goto fallback;
2038
2039     switch (mode)
2040     {
2041     case GRADIENT_FILL_RECT_H:
2042     case GRADIENT_FILL_RECT_V:
2043         for (i = 0; i < ngrad; i++, rect++)
2044         {
2045             const TRIVERTEX *v1 = vert_array + rect->UpperLeft;
2046             const TRIVERTEX *v2 = vert_array + rect->LowerRight;
2047
2048             colors[0].red   = v1->Red * 257 / 256;
2049             colors[0].green = v1->Green * 257 / 256;
2050             colors[0].blue  = v1->Blue * 257 / 256;
2051             colors[1].red   = v2->Red * 257 / 256;
2052             colors[1].green = v2->Green * 257 / 256;
2053             colors[1].blue  = v2->Blue * 257 / 256;
2054             /* always ignore alpha since otherwise xrender will want to pre-multiply the colors */
2055             colors[0].alpha = colors[1].alpha = 65535;
2056
2057             pt[0].x = v1->x;
2058             pt[0].y = v1->y;
2059             pt[1].x = v2->x;
2060             pt[1].y = v2->y;
2061             LPtoDP( dev->hdc, pt, 2 );
2062             if (mode == GRADIENT_FILL_RECT_H)
2063             {
2064                 gradient.p1.y = gradient.p2.y = 0;
2065                 if (pt[1].x > pt[0].x)
2066                 {
2067                     gradient.p1.x = 0;
2068                     gradient.p2.x = (pt[1].x - pt[0].x) << 16;
2069                 }
2070                 else
2071                 {
2072                     gradient.p1.x = (pt[0].x - pt[1].x) << 16;
2073                     gradient.p2.x = 0;
2074                 }
2075             }
2076             else
2077             {
2078                 gradient.p1.x = gradient.p2.x = 0;
2079                 if (pt[1].y > pt[0].y)
2080                 {
2081                     gradient.p1.y = 0;
2082                     gradient.p2.y = (pt[1].y - pt[0].y) << 16;
2083                 }
2084                 else
2085                 {
2086                     gradient.p1.y = (pt[0].y - pt[1].y) << 16;
2087                     gradient.p2.y = 0;
2088                 }
2089             }
2090
2091             rc.left   = min( pt[0].x, pt[1].x );
2092             rc.top    = min( pt[0].y, pt[1].y );
2093             rc.right  = max( pt[0].x, pt[1].x );
2094             rc.bottom = max( pt[0].y, pt[1].y );
2095
2096             TRACE( "%u gradient %s colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n",
2097                    mode, wine_dbgstr_rect( &rc ),
2098                    colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha,
2099                    colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha );
2100
2101             dst_pict = get_xrender_picture( physdev, 0, NULL );
2102
2103             src_pict = pXRenderCreateLinearGradient( gdi_display, &gradient, stops, colors, 2 );
2104             xrender_blit( PictOpSrc, src_pict, 0, dst_pict,
2105                           0, 0, rc.right - rc.left, rc.bottom - rc.top,
2106                           physdev->x11dev->dc_rect.left + rc.left,
2107                           physdev->x11dev->dc_rect.top + rc.top,
2108                           rc.right - rc.left, rc.bottom - rc.top, 1, 1 );
2109             pXRenderFreePicture( gdi_display, src_pict );
2110             add_device_bounds( physdev->x11dev, &rc );
2111         }
2112         return TRUE;
2113     }
2114
2115 fallback:
2116 #endif
2117     dev = GET_NEXT_PHYSDEV( dev, pGradientFill );
2118     return dev->funcs->pGradientFill( dev, vert_array, nvert, grad_array, ngrad, mode );
2119 }
2120
2121 /***********************************************************************
2122  *           xrenderdrv_SelectBrush
2123  */
2124 static HBRUSH xrenderdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern )
2125 {
2126     struct xrender_physdev *physdev = get_xrender_dev( dev );
2127     Pixmap pixmap;
2128     XVisualInfo vis = default_visual;
2129     XRenderPictFormat *format = physdev->pict_format;
2130
2131     if (!pattern) goto x11drv_fallback;
2132     if (pattern->info->bmiHeader.biBitCount == 1) goto x11drv_fallback;
2133     if (physdev->format == WXR_FORMAT_MONO) goto x11drv_fallback;
2134
2135     vis.depth      = format->depth;
2136     vis.red_mask   = format->direct.redMask   << format->direct.red;
2137     vis.green_mask = format->direct.greenMask << format->direct.green;
2138     vis.blue_mask  = format->direct.blueMask  << format->direct.blue;
2139
2140     pixmap = create_pixmap_from_image( physdev->dev.hdc, &vis, pattern->info,
2141                                        &pattern->bits, pattern->usage );
2142     if (!pixmap) return 0;
2143
2144     if (physdev->x11dev->brush.pixmap) XFreePixmap( gdi_display, physdev->x11dev->brush.pixmap );
2145     physdev->x11dev->brush.pixmap = pixmap;
2146     physdev->x11dev->brush.fillStyle = FillTiled;
2147     physdev->x11dev->brush.pixel = 0;  /* ignored */
2148     physdev->x11dev->brush.style = BS_PATTERN;
2149     return hbrush;
2150
2151 x11drv_fallback:
2152     dev = GET_NEXT_PHYSDEV( dev, pSelectBrush );
2153     return dev->funcs->pSelectBrush( dev, hbrush, pattern );
2154 }
2155
2156
2157 static const struct gdi_dc_funcs xrender_funcs =
2158 {
2159     NULL,                               /* pAbortDoc */
2160     NULL,                               /* pAbortPath */
2161     xrenderdrv_AlphaBlend,              /* pAlphaBlend */
2162     NULL,                               /* pAngleArc */
2163     NULL,                               /* pArc */
2164     NULL,                               /* pArcTo */
2165     NULL,                               /* pBeginPath */
2166     xrenderdrv_BlendImage,              /* pBlendImage */
2167     NULL,                               /* pChord */
2168     NULL,                               /* pCloseFigure */
2169     xrenderdrv_CreateCompatibleDC,      /* pCreateCompatibleDC */
2170     xrenderdrv_CreateDC,                /* pCreateDC */
2171     xrenderdrv_DeleteDC,                /* pDeleteDC */
2172     NULL,                               /* pDeleteObject */
2173     NULL,                               /* pDeviceCapabilities */
2174     NULL,                               /* pEllipse */
2175     NULL,                               /* pEndDoc */
2176     NULL,                               /* pEndPage */
2177     NULL,                               /* pEndPath */
2178     NULL,                               /* pEnumFonts */
2179     NULL,                               /* pEnumICMProfiles */
2180     NULL,                               /* pExcludeClipRect */
2181     NULL,                               /* pExtDeviceMode */
2182     xrenderdrv_ExtEscape,               /* pExtEscape */
2183     NULL,                               /* pExtFloodFill */
2184     NULL,                               /* pExtSelectClipRgn */
2185     xrenderdrv_ExtTextOut,              /* pExtTextOut */
2186     NULL,                               /* pFillPath */
2187     NULL,                               /* pFillRgn */
2188     NULL,                               /* pFlattenPath */
2189     NULL,                               /* pFontIsLinked */
2190     NULL,                               /* pFrameRgn */
2191     NULL,                               /* pGdiComment */
2192     NULL,                               /* pGdiRealizationInfo */
2193     NULL,                               /* pGetBoundsRect */
2194     NULL,                               /* pGetCharABCWidths */
2195     NULL,                               /* pGetCharABCWidthsI */
2196     NULL,                               /* pGetCharWidth */
2197     NULL,                               /* pGetDeviceCaps */
2198     NULL,                               /* pGetDeviceGammaRamp */
2199     NULL,                               /* pGetFontData */
2200     NULL,                               /* pGetFontUnicodeRanges */
2201     NULL,                               /* pGetGlyphIndices */
2202     NULL,                               /* pGetGlyphOutline */
2203     NULL,                               /* pGetICMProfile */
2204     NULL,                               /* pGetImage */
2205     NULL,                               /* pGetKerningPairs */
2206     NULL,                               /* pGetNearestColor */
2207     NULL,                               /* pGetOutlineTextMetrics */
2208     NULL,                               /* pGetPixel */
2209     NULL,                               /* pGetSystemPaletteEntries */
2210     NULL,                               /* pGetTextCharsetInfo */
2211     NULL,                               /* pGetTextExtentExPoint */
2212     NULL,                               /* pGetTextExtentExPointI */
2213     NULL,                               /* pGetTextFace */
2214     NULL,                               /* pGetTextMetrics */
2215     xrenderdrv_GradientFill,            /* pGradientFill */
2216     NULL,                               /* pIntersectClipRect */
2217     NULL,                               /* pInvertRgn */
2218     NULL,                               /* pLineTo */
2219     NULL,                               /* pModifyWorldTransform */
2220     NULL,                               /* pMoveTo */
2221     NULL,                               /* pOffsetClipRgn */
2222     NULL,                               /* pOffsetViewportOrg */
2223     NULL,                               /* pOffsetWindowOrg */
2224     NULL,                               /* pPaintRgn */
2225     NULL,                               /* pPatBlt */
2226     NULL,                               /* pPie */
2227     NULL,                               /* pPolyBezier */
2228     NULL,                               /* pPolyBezierTo */
2229     NULL,                               /* pPolyDraw */
2230     NULL,                               /* pPolyPolygon */
2231     NULL,                               /* pPolyPolyline */
2232     NULL,                               /* pPolygon */
2233     NULL,                               /* pPolyline */
2234     NULL,                               /* pPolylineTo */
2235     xrenderdrv_PutImage,                /* pPutImage */
2236     NULL,                               /* pRealizeDefaultPalette */
2237     NULL,                               /* pRealizePalette */
2238     NULL,                               /* pRectangle */
2239     NULL,                               /* pResetDC */
2240     NULL,                               /* pRestoreDC */
2241     NULL,                               /* pRoundRect */
2242     NULL,                               /* pSaveDC */
2243     NULL,                               /* pScaleViewportExt */
2244     NULL,                               /* pScaleWindowExt */
2245     NULL,                               /* pSelectBitmap */
2246     xrenderdrv_SelectBrush,             /* pSelectBrush */
2247     NULL,                               /* pSelectClipPath */
2248     xrenderdrv_SelectFont,              /* pSelectFont */
2249     NULL,                               /* pSelectPalette */
2250     NULL,                               /* pSelectPen */
2251     NULL,                               /* pSetArcDirection */
2252     NULL,                               /* pSetBkColor */
2253     NULL,                               /* pSetBkMode */
2254     NULL,                               /* pSetBoundsRect */
2255     NULL,                               /* pSetDCBrushColor */
2256     NULL,                               /* pSetDCPenColor */
2257     NULL,                               /* pSetDIBitsToDevice */
2258     xrenderdrv_SetDeviceClipping,       /* pSetDeviceClipping */
2259     NULL,                               /* pSetDeviceGammaRamp */
2260     NULL,                               /* pSetLayout */
2261     NULL,                               /* pSetMapMode */
2262     NULL,                               /* pSetMapperFlags */
2263     NULL,                               /* pSetPixel */
2264     NULL,                               /* pSetPolyFillMode */
2265     NULL,                               /* pSetROP2 */
2266     NULL,                               /* pSetRelAbs */
2267     NULL,                               /* pSetStretchBltMode */
2268     NULL,                               /* pSetTextAlign */
2269     NULL,                               /* pSetTextCharacterExtra */
2270     NULL,                               /* pSetTextColor */
2271     NULL,                               /* pSetTextJustification */
2272     NULL,                               /* pSetViewportExt */
2273     NULL,                               /* pSetViewportOrg */
2274     NULL,                               /* pSetWindowExt */
2275     NULL,                               /* pSetWindowOrg */
2276     NULL,                               /* pSetWorldTransform */
2277     NULL,                               /* pStartDoc */
2278     NULL,                               /* pStartPage */
2279     xrenderdrv_StretchBlt,              /* pStretchBlt */
2280     NULL,                               /* pStretchDIBits */
2281     NULL,                               /* pStrokeAndFillPath */
2282     NULL,                               /* pStrokePath */
2283     NULL,                               /* pUnrealizePalette */
2284     NULL,                               /* pWidenPath */
2285     NULL,                               /* wine_get_wgl_driver */
2286     GDI_PRIORITY_GRAPHICS_DRV + 10      /* priority */
2287 };
2288
2289 #else /* SONAME_LIBXRENDER */
2290
2291 const struct gdi_dc_funcs *X11DRV_XRender_Init(void)
2292 {
2293     TRACE("XRender support not compiled in.\n");
2294     return NULL;
2295 }
2296
2297 #endif /* SONAME_LIBXRENDER */