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