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