2 * Functions to use the XRender extension
4 * Copyright 2001, 2002 Huw D M Davies for CodeWeavers
5 * Copyright 2009 Roderick Colenbrander
6 * Copyright 2011 Alexandre Julliard
9 * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
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.
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.
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
26 #include "wine/port.h"
37 #include "wine/library.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(xrender
);
43 #ifdef SONAME_LIBXRENDER
45 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
48 #include <X11/extensions/Xrender.h>
50 #ifndef RepeatNone /* added in 0.10 */
52 #define RepeatNormal 1
54 #define RepeatReflect 3
72 WXR_INVALID_FORMAT
= WXR_NB_FORMATS
75 typedef struct wine_xrender_format_template
79 unsigned int alphaMask
;
83 unsigned int greenMask
;
85 unsigned int blueMask
;
86 } WineXRenderFormatTemplate
;
88 static const WineXRenderFormatTemplate wxr_formats_template
[WXR_NB_FORMATS
] =
90 /* Format depth alpha mask red mask green mask blue mask*/
91 /* WXR_FORMAT_MONO */ { 1, 0, 0x01, 0, 0, 0, 0, 0, 0 },
92 /* WXR_FORMAT_GRAY */ { 8, 0, 0xff, 0, 0, 0, 0, 0, 0 },
93 /* WXR_FORMAT_X1R5G5B5 */ { 16, 0, 0, 10, 0x1f, 5, 0x1f, 0, 0x1f },
94 /* WXR_FORMAT_X1B5G5R5 */ { 16, 0, 0, 0, 0x1f, 5, 0x1f, 10, 0x1f },
95 /* WXR_FORMAT_R5G6B5 */ { 16, 0, 0, 11, 0x1f, 5, 0x3f, 0, 0x1f },
96 /* WXR_FORMAT_B5G6R5 */ { 16, 0, 0, 0, 0x1f, 5, 0x3f, 11, 0x1f },
97 /* WXR_FORMAT_R8G8B8 */ { 24, 0, 0, 16, 0xff, 8, 0xff, 0, 0xff },
98 /* WXR_FORMAT_B8G8R8 */ { 24, 0, 0, 0, 0xff, 8, 0xff, 16, 0xff },
99 /* WXR_FORMAT_A8R8G8B8 */ { 32, 24, 0xff, 16, 0xff, 8, 0xff, 0, 0xff },
100 /* WXR_FORMAT_B8G8R8A8 */ { 32, 0, 0xff, 8, 0xff, 16, 0xff, 24, 0xff },
101 /* WXR_FORMAT_X8R8G8B8 */ { 32, 0, 0, 16, 0xff, 8, 0xff, 0, 0xff },
102 /* WXR_FORMAT_B8G8R8X8 */ { 32, 0, 0, 8, 0xff, 16, 0xff, 24, 0xff },
105 static const ColorShifts wxr_color_shifts
[WXR_NB_FORMATS
] =
107 /* format phys red phys green phys blue log red log green log blue */
108 /* WXR_FORMAT_MONO */ { { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 } },
109 /* WXR_FORMAT_GRAY */ { { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 } },
110 /* WXR_FORMAT_X1R5G5B5 */ { {10,5,31}, { 5,5,31}, { 0,5,31}, {10,5,31}, { 5,5,31}, { 0,5,31} },
111 /* WXR_FORMAT_X1B5G5R5 */ { { 0,5,31}, { 5,5,31}, {10,5,31}, { 0,5,31}, { 5,5,31}, {10,5,31} },
112 /* WXR_FORMAT_R5G6B5 */ { {11,5,31}, { 5,6,63}, { 0,5,31}, {11,5,31}, { 5,6,63}, { 0,5,31} },
113 /* WXR_FORMAT_B5G6R5 */ { { 0,5,31}, { 5,6,63}, {11,5,31}, { 0,5,31}, { 5,6,63}, {11,5,31} },
114 /* WXR_FORMAT_R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
115 /* WXR_FORMAT_B8G8R8 */ { { 0,8,255}, { 8,8,255}, {16,8,255}, { 0,8,255}, { 8,8,255}, {16,8,255} },
116 /* WXR_FORMAT_A8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
117 /* WXR_FORMAT_B8G8R8A8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
118 /* WXR_FORMAT_X8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
119 /* WXR_FORMAT_B8G8R8X8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
122 static enum wxr_format default_format
= WXR_INVALID_FORMAT
;
123 static XRenderPictFormat
*pict_formats
[WXR_NB_FORMATS
+ 1 /* invalid format */];
129 SIZE devsize
; /* size in device coords */
133 #define INITIAL_REALIZED_BUF_SIZE 128
135 typedef enum { AA_None
= 0, AA_Grey
, AA_RGB
, AA_BGR
, AA_VRGB
, AA_VBGR
, AA_MAXVALUE
} AA_Type
;
140 XRenderPictFormat
*font_format
;
144 } gsCacheEntryFormat
;
150 gsCacheEntryFormat
* format
[AA_MAXVALUE
];
155 struct xrender_physdev
157 struct gdi_physdev dev
;
158 X11DRV_PDEVICE
*x11dev
;
160 enum wxr_format format
;
165 XRenderPictFormat
*pict_format
;
168 static inline struct xrender_physdev
*get_xrender_dev( PHYSDEV dev
)
170 return (struct xrender_physdev
*)dev
;
173 static const struct gdi_dc_funcs xrender_funcs
;
175 static gsCacheEntry
*glyphsetCache
= NULL
;
176 static DWORD glyphsetCacheSize
= 0;
177 static INT lastfree
= -1;
180 #define INIT_CACHE_SIZE 10
182 static int antialias
= 1;
184 static void *xrender_handle
;
186 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
187 MAKE_FUNCPTR(XRenderAddGlyphs
)
188 MAKE_FUNCPTR(XRenderChangePicture
)
189 MAKE_FUNCPTR(XRenderComposite
)
190 MAKE_FUNCPTR(XRenderCompositeText16
)
191 MAKE_FUNCPTR(XRenderCreateGlyphSet
)
192 MAKE_FUNCPTR(XRenderCreatePicture
)
193 MAKE_FUNCPTR(XRenderFillRectangle
)
194 MAKE_FUNCPTR(XRenderFindFormat
)
195 MAKE_FUNCPTR(XRenderFindVisualFormat
)
196 MAKE_FUNCPTR(XRenderFreeGlyphSet
)
197 MAKE_FUNCPTR(XRenderFreePicture
)
198 MAKE_FUNCPTR(XRenderSetPictureClipRectangles
)
199 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
200 MAKE_FUNCPTR(XRenderCreateLinearGradient
)
202 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
203 MAKE_FUNCPTR(XRenderSetPictureTransform
)
205 MAKE_FUNCPTR(XRenderQueryExtension
)
207 #ifdef SONAME_LIBFONTCONFIG
208 #include <fontconfig/fontconfig.h>
209 MAKE_FUNCPTR(FcConfigSubstitute
)
210 MAKE_FUNCPTR(FcDefaultSubstitute
)
211 MAKE_FUNCPTR(FcFontMatch
)
213 MAKE_FUNCPTR(FcPatternCreate
)
214 MAKE_FUNCPTR(FcPatternDestroy
)
215 MAKE_FUNCPTR(FcPatternAddInteger
)
216 MAKE_FUNCPTR(FcPatternAddString
)
217 MAKE_FUNCPTR(FcPatternGetBool
)
218 MAKE_FUNCPTR(FcPatternGetInteger
)
219 MAKE_FUNCPTR(FcPatternGetString
)
220 static void *fontconfig_handle
;
221 static BOOL fontconfig_installed
;
226 static CRITICAL_SECTION xrender_cs
;
227 static CRITICAL_SECTION_DEBUG critsect_debug
=
230 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
231 0, 0, { (DWORD_PTR
)(__FILE__
": xrender_cs") }
233 static CRITICAL_SECTION xrender_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
235 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
236 ( ( (ULONG)_x4 << 24 ) | \
237 ( (ULONG)_x3 << 16 ) | \
238 ( (ULONG)_x2 << 8 ) | \
241 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
243 #define GASP_GRIDFIT 0x01
244 #define GASP_DOGRAY 0x02
246 #ifdef WORDS_BIGENDIAN
247 #define get_be_word(x) (x)
248 #define NATIVE_BYTE_ORDER MSBFirst
250 #define get_be_word(x) RtlUshortByteSwap(x)
251 #define NATIVE_BYTE_ORDER LSBFirst
254 static BOOL
has_alpha( enum wxr_format format
)
256 return (format
== WXR_FORMAT_A8R8G8B8
|| format
== WXR_FORMAT_B8G8R8A8
);
259 static enum wxr_format
get_format_without_alpha( enum wxr_format format
)
263 case WXR_FORMAT_A8R8G8B8
: return WXR_FORMAT_X8R8G8B8
;
264 case WXR_FORMAT_B8G8R8A8
: return WXR_FORMAT_B8G8R8X8
;
265 default: return format
;
269 static BOOL
get_xrender_template(const WineXRenderFormatTemplate
*fmt
, XRenderPictFormat
*templ
, unsigned long *mask
)
272 templ
->type
= PictTypeDirect
;
273 templ
->depth
= fmt
->depth
;
274 templ
->direct
.alpha
= fmt
->alpha
;
275 templ
->direct
.alphaMask
= fmt
->alphaMask
;
276 templ
->direct
.red
= fmt
->red
;
277 templ
->direct
.redMask
= fmt
->redMask
;
278 templ
->direct
.green
= fmt
->green
;
279 templ
->direct
.greenMask
= fmt
->greenMask
;
280 templ
->direct
.blue
= fmt
->blue
;
281 templ
->direct
.blueMask
= fmt
->blueMask
;
284 *mask
= PictFormatType
| PictFormatDepth
| PictFormatAlpha
| PictFormatAlphaMask
| PictFormatRed
| PictFormatRedMask
| PictFormatGreen
| PictFormatGreenMask
| PictFormatBlue
| PictFormatBlueMask
;
289 static BOOL
is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate
*fmt
)
291 if(fmt
->depth
!= screen_depth
)
293 if( (fmt
->redMask
<< fmt
->red
) != visual
->red_mask
)
295 if( (fmt
->greenMask
<< fmt
->green
) != visual
->green_mask
)
297 if( (fmt
->blueMask
<< fmt
->blue
) != visual
->blue_mask
)
300 /* We never select a default ARGB visual */
307 static int load_xrender_formats(void)
312 for (i
= 0; i
< WXR_NB_FORMATS
; i
++)
314 XRenderPictFormat templ
;
316 if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template
[i
]))
319 pict_formats
[i
] = pXRenderFindVisualFormat(gdi_display
, visual
);
320 if (!pict_formats
[i
])
322 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
323 if (visual
->class == DirectColor
)
326 if (XMatchVisualInfo( gdi_display
, DefaultScreen(gdi_display
),
327 screen_depth
, TrueColor
, &info
))
329 pict_formats
[i
] = pXRenderFindVisualFormat(gdi_display
, info
.visual
);
330 if (pict_formats
[i
]) visual
= info
.visual
;
335 if (pict_formats
[i
]) default_format
= i
;
339 unsigned long mask
= 0;
340 get_xrender_template(&wxr_formats_template
[i
], &templ
, &mask
);
343 pict_formats
[i
] = pXRenderFindFormat(gdi_display
, mask
, &templ
, 0);
349 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats
[i
]->id
, i
);
355 /***********************************************************************
356 * X11DRV_XRender_Init
358 * Let's see if our XServer has the extension available
361 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
366 if (!client_side_with_render
) return NULL
;
367 if (!(xrender_handle
= wine_dlopen(SONAME_LIBXRENDER
, RTLD_NOW
, NULL
, 0))) return NULL
;
369 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) return NULL
370 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0)
371 LOAD_FUNCPTR(XRenderAddGlyphs
);
372 LOAD_FUNCPTR(XRenderChangePicture
);
373 LOAD_FUNCPTR(XRenderComposite
);
374 LOAD_FUNCPTR(XRenderCompositeText16
);
375 LOAD_FUNCPTR(XRenderCreateGlyphSet
);
376 LOAD_FUNCPTR(XRenderCreatePicture
);
377 LOAD_FUNCPTR(XRenderFillRectangle
);
378 LOAD_FUNCPTR(XRenderFindFormat
);
379 LOAD_FUNCPTR(XRenderFindVisualFormat
);
380 LOAD_FUNCPTR(XRenderFreeGlyphSet
);
381 LOAD_FUNCPTR(XRenderFreePicture
);
382 LOAD_FUNCPTR(XRenderSetPictureClipRectangles
);
383 LOAD_FUNCPTR(XRenderQueryExtension
);
384 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
385 LOAD_OPTIONAL_FUNCPTR(XRenderCreateLinearGradient
);
387 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
388 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform
);
390 #undef LOAD_OPTIONAL_FUNCPTR
394 ok
= pXRenderQueryExtension(gdi_display
, &event_base
, &xrender_error_base
);
396 if (!ok
) return NULL
;
398 TRACE("Xrender is up and running error_base = %d\n", xrender_error_base
);
399 if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
401 ERR_(winediag
)("Wine has detected that you probably have a buggy version "
402 "of libXrender. Because of this client side font rendering "
403 "will be disabled. Please upgrade this library.\n");
407 if (!visual
->red_mask
|| !visual
->green_mask
|| !visual
->blue_mask
)
409 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
413 #ifdef SONAME_LIBFONTCONFIG
414 if ((fontconfig_handle
= wine_dlopen(SONAME_LIBFONTCONFIG
, RTLD_NOW
, NULL
, 0)))
416 #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;}
417 LOAD_FUNCPTR(FcConfigSubstitute
);
418 LOAD_FUNCPTR(FcDefaultSubstitute
);
419 LOAD_FUNCPTR(FcFontMatch
);
420 LOAD_FUNCPTR(FcInit
);
421 LOAD_FUNCPTR(FcPatternCreate
);
422 LOAD_FUNCPTR(FcPatternDestroy
);
423 LOAD_FUNCPTR(FcPatternAddInteger
);
424 LOAD_FUNCPTR(FcPatternAddString
);
425 LOAD_FUNCPTR(FcPatternGetBool
);
426 LOAD_FUNCPTR(FcPatternGetInteger
);
427 LOAD_FUNCPTR(FcPatternGetString
);
429 fontconfig_installed
= pFcInit();
431 else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG
"\n" );
436 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
437 sizeof(*glyphsetCache
) * INIT_CACHE_SIZE
);
439 glyphsetCacheSize
= INIT_CACHE_SIZE
;
441 for(i
= 0; i
< INIT_CACHE_SIZE
; i
++) {
442 glyphsetCache
[i
].next
= i
+ 1;
443 glyphsetCache
[i
].count
= -1;
445 glyphsetCache
[i
-1].next
= -1;
447 if(screen_depth
<= 8 || !client_side_antialias_with_render
) antialias
= 0;
449 return &xrender_funcs
;
452 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
453 static void get_xrender_color( struct xrender_physdev
*physdev
, COLORREF src_color
, XRenderColor
*dst_color
)
455 if (src_color
& (1 << 24)) /* PALETTEINDEX */
457 HPALETTE pal
= GetCurrentObject( physdev
->dev
.hdc
, OBJ_PAL
);
458 PALETTEENTRY pal_ent
;
460 if (!GetPaletteEntries( pal
, LOWORD(src_color
), 1, &pal_ent
))
461 GetPaletteEntries( pal
, 0, 1, &pal_ent
);
462 dst_color
->red
= pal_ent
.peRed
* 257;
463 dst_color
->green
= pal_ent
.peGreen
* 257;
464 dst_color
->blue
= pal_ent
.peBlue
* 257;
468 if (src_color
>> 16 == 0x10ff) src_color
= 0; /* DIBINDEX */
470 dst_color
->red
= GetRValue( src_color
) * 257;
471 dst_color
->green
= GetGValue( src_color
) * 257;
472 dst_color
->blue
= GetBValue( src_color
) * 257;
475 if (physdev
->format
== WXR_FORMAT_MONO
&& !dst_color
->red
&& !dst_color
->green
&& !dst_color
->blue
)
476 dst_color
->alpha
= 0;
478 dst_color
->alpha
= 0xffff;
481 static enum wxr_format
get_xrender_format_from_bitmapinfo( const BITMAPINFO
*info
)
483 if (info
->bmiHeader
.biPlanes
!= 1) return WXR_INVALID_FORMAT
;
485 switch (info
->bmiHeader
.biBitCount
)
488 return WXR_FORMAT_MONO
;
493 if (info
->bmiHeader
.biCompression
!= BI_RGB
) break;
494 return WXR_FORMAT_R8G8B8
;
497 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
499 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
502 for (i
= 0; i
< WXR_NB_FORMATS
; i
++)
504 if (info
->bmiHeader
.biBitCount
== wxr_formats_template
[i
].depth
&&
505 colors
[0] == (wxr_formats_template
[i
].redMask
<< wxr_formats_template
[i
].red
) &&
506 colors
[1] == (wxr_formats_template
[i
].greenMask
<< wxr_formats_template
[i
].green
) &&
507 colors
[2] == (wxr_formats_template
[i
].blueMask
<< wxr_formats_template
[i
].blue
))
512 if (info
->bmiHeader
.biCompression
!= BI_RGB
) break;
513 return (info
->bmiHeader
.biBitCount
== 16) ? WXR_FORMAT_X1R5G5B5
: WXR_FORMAT_A8R8G8B8
;
515 return WXR_INVALID_FORMAT
;
518 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
519 static void set_xrender_transformation(Picture src_pict
, double xscale
, double yscale
, int xoffset
, int yoffset
)
521 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
522 XTransform xform
= {{
523 { XDoubleToFixed(xscale
), XDoubleToFixed(0), XDoubleToFixed(xoffset
) },
524 { XDoubleToFixed(0), XDoubleToFixed(yscale
), XDoubleToFixed(yoffset
) },
525 { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
528 pXRenderSetPictureTransform(gdi_display
, src_pict
, &xform
);
532 static void update_xrender_clipping( struct xrender_physdev
*dev
, HRGN rgn
)
534 XRenderPictureAttributes pa
;
541 pXRenderChangePicture( gdi_display
, dev
->pict
, CPClipMask
, &pa
);
544 else if ((data
= X11DRV_GetRegionData( rgn
, 0 )))
547 pXRenderSetPictureClipRectangles( gdi_display
, dev
->pict
,
548 dev
->x11dev
->dc_rect
.left
, dev
->x11dev
->dc_rect
.top
,
549 (XRectangle
*)data
->Buffer
, data
->rdh
.nCount
);
551 HeapFree( GetProcessHeap(), 0, data
);
556 static Picture
get_xrender_picture( struct xrender_physdev
*dev
, HRGN clip_rgn
, const RECT
*clip_rect
)
558 if (!dev
->pict
&& dev
->pict_format
)
560 XRenderPictureAttributes pa
;
563 pa
.subwindow_mode
= IncludeInferiors
;
564 dev
->pict
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
565 dev
->pict_format
, CPSubwindowMode
, &pa
);
567 TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
568 dev
->pict
, dev
->dev
.hdc
, dev
->x11dev
->drawable
);
569 dev
->update_clip
= (dev
->region
!= 0);
574 HRGN rgn
= CreateRectRgnIndirect( clip_rect
);
575 if (clip_rgn
) CombineRgn( rgn
, rgn
, clip_rgn
, RGN_AND
);
576 if (dev
->region
) CombineRgn( rgn
, rgn
, dev
->region
, RGN_AND
);
577 update_xrender_clipping( dev
, rgn
);
584 HRGN rgn
= CreateRectRgn( 0, 0, 0, 0 );
585 CombineRgn( rgn
, clip_rgn
, dev
->region
, RGN_AND
);
586 update_xrender_clipping( dev
, rgn
);
589 else update_xrender_clipping( dev
, clip_rgn
);
591 else if (dev
->update_clip
) update_xrender_clipping( dev
, dev
->region
);
593 dev
->update_clip
= (clip_rect
|| clip_rgn
); /* have to update again if we are using a custom region */
597 static Picture
get_xrender_picture_source( struct xrender_physdev
*dev
, BOOL repeat
)
599 if (!dev
->pict_src
&& dev
->pict_format
)
601 XRenderPictureAttributes pa
;
604 pa
.subwindow_mode
= IncludeInferiors
;
605 pa
.repeat
= repeat
? RepeatNormal
: RepeatNone
;
606 dev
->pict_src
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
607 dev
->pict_format
, CPSubwindowMode
|CPRepeat
, &pa
);
610 TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
611 dev
->pict_src
, dev
->dev
.hdc
, dev
->x11dev
->drawable
, pa
.repeat
);
614 return dev
->pict_src
;
617 static void free_xrender_picture( struct xrender_physdev
*dev
)
619 if (dev
->pict
|| dev
->pict_src
)
622 XFlush( gdi_display
);
625 TRACE("freeing pict = %lx dc = %p\n", dev
->pict
, dev
->dev
.hdc
);
626 pXRenderFreePicture(gdi_display
, dev
->pict
);
631 TRACE("freeing pict = %lx dc = %p\n", dev
->pict_src
, dev
->dev
.hdc
);
632 pXRenderFreePicture(gdi_display
, dev
->pict_src
);
639 /* return a mask picture used to force alpha to 0 */
640 static Picture
get_no_alpha_mask(void)
642 static Pixmap pixmap
;
648 XRenderPictureAttributes pa
;
651 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
652 pa
.repeat
= RepeatNormal
;
653 pa
.component_alpha
= True
;
654 pict
= pXRenderCreatePicture( gdi_display
, pixmap
, pict_formats
[WXR_FORMAT_A8R8G8B8
],
655 CPRepeat
|CPComponentAlpha
, &pa
);
656 col
.red
= col
.green
= col
.blue
= 0xffff;
658 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
664 static BOOL
fontcmp(LFANDSIZE
*p1
, LFANDSIZE
*p2
)
666 if(p1
->hash
!= p2
->hash
) return TRUE
;
667 if(memcmp(&p1
->devsize
, &p2
->devsize
, sizeof(p1
->devsize
))) return TRUE
;
668 if(memcmp(&p1
->xform
, &p2
->xform
, sizeof(p1
->xform
))) return TRUE
;
669 if(memcmp(&p1
->lf
, &p2
->lf
, offsetof(LOGFONTW
, lfFaceName
))) return TRUE
;
670 return strcmpiW(p1
->lf
.lfFaceName
, p2
->lf
.lfFaceName
);
674 static void walk_cache(void)
678 EnterCriticalSection(&xrender_cs
);
679 for(i
=mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
680 TRACE("item %d\n", i
);
681 LeaveCriticalSection(&xrender_cs
);
685 static int LookupEntry(LFANDSIZE
*plfsz
)
689 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
691 if(glyphsetCache
[i
].count
== -1) break; /* reached free list so stop */
693 if(!fontcmp(&glyphsetCache
[i
].lfsz
, plfsz
)) {
694 glyphsetCache
[i
].count
++;
696 glyphsetCache
[prev_i
].next
= glyphsetCache
[i
].next
;
697 glyphsetCache
[i
].next
= mru
;
700 TRACE("found font in cache %d\n", i
);
705 TRACE("font not in cache\n");
709 static void FreeEntry(int entry
)
713 for(format
= 0; format
< AA_MAXVALUE
; format
++) {
714 gsCacheEntryFormat
* formatEntry
;
716 if( !glyphsetCache
[entry
].format
[format
] )
719 formatEntry
= glyphsetCache
[entry
].format
[format
];
721 if(formatEntry
->glyphset
) {
723 pXRenderFreeGlyphSet(gdi_display
, formatEntry
->glyphset
);
725 formatEntry
->glyphset
= 0;
727 if(formatEntry
->nrealized
) {
728 HeapFree(GetProcessHeap(), 0, formatEntry
->realized
);
729 formatEntry
->realized
= NULL
;
730 HeapFree(GetProcessHeap(), 0, formatEntry
->gis
);
731 formatEntry
->gis
= NULL
;
732 formatEntry
->nrealized
= 0;
735 HeapFree(GetProcessHeap(), 0, formatEntry
);
736 glyphsetCache
[entry
].format
[format
] = NULL
;
740 static int AllocEntry(void)
742 int best
= -1, prev_best
= -1, i
, prev_i
= -1;
745 assert(glyphsetCache
[lastfree
].count
== -1);
746 glyphsetCache
[lastfree
].count
= 1;
748 lastfree
= glyphsetCache
[lastfree
].next
;
750 glyphsetCache
[best
].next
= mru
;
753 TRACE("empty space at %d, next lastfree = %d\n", mru
, lastfree
);
757 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
758 if(glyphsetCache
[i
].count
== 0) {
766 TRACE("freeing unused glyphset at cache %d\n", best
);
768 glyphsetCache
[best
].count
= 1;
770 glyphsetCache
[prev_best
].next
= glyphsetCache
[best
].next
;
771 glyphsetCache
[best
].next
= mru
;
779 TRACE("Growing cache\n");
782 glyphsetCache
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
784 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
785 * sizeof(*glyphsetCache
));
787 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
788 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
789 * sizeof(*glyphsetCache
));
791 for(best
= i
= glyphsetCacheSize
; i
< glyphsetCacheSize
+ INIT_CACHE_SIZE
;
793 glyphsetCache
[i
].next
= i
+ 1;
794 glyphsetCache
[i
].count
= -1;
796 glyphsetCache
[i
-1].next
= -1;
797 glyphsetCacheSize
+= INIT_CACHE_SIZE
;
799 lastfree
= glyphsetCache
[best
].next
;
800 glyphsetCache
[best
].count
= 1;
801 glyphsetCache
[best
].next
= mru
;
803 TRACE("new free cache slot at %d\n", mru
);
807 static BOOL
get_gasp_flags(HDC hdc
, WORD
*flags
)
817 size
= GetFontData(hdc
, MS_GASP_TAG
, 0, NULL
, 0);
818 if(size
== GDI_ERROR
)
821 gasp
= buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
822 GetFontData(hdc
, MS_GASP_TAG
, 0, gasp
, size
);
824 GetTextMetricsW(hdc
, &tm
);
825 ppem
= abs(X11DRV_YWStoDS(hdc
, tm
.tmAscent
+ tm
.tmDescent
- tm
.tmInternalLeading
));
828 num_recs
= get_be_word(*gasp
);
832 *flags
= get_be_word(*(gasp
+ 1));
833 if(ppem
<= get_be_word(*gasp
))
837 TRACE("got flags %04x for ppem %d\n", *flags
, ppem
);
839 HeapFree(GetProcessHeap(), 0, buffer
);
843 static AA_Type
get_antialias_type( HDC hdc
, BOOL subpixel
, BOOL hinter
)
847 UINT font_smoothing_type
, font_smoothing_orientation
;
850 SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE
, 0, &font_smoothing_type
, 0) &&
851 font_smoothing_type
== FE_FONTSMOOTHINGCLEARTYPE
)
853 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION
, 0,
854 &font_smoothing_orientation
, 0) &&
855 font_smoothing_orientation
== FE_FONTSMOOTHINGORIENTATIONBGR
)
862 If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
863 But, Wine's subpixel rendering can support the portrait mode.
866 else if (!hinter
|| !get_gasp_flags(hdc
, &flags
) || flags
& GASP_DOGRAY
)
874 static int GetCacheEntry( HDC hdc
, LFANDSIZE
*plfsz
)
879 static int hinter
= -1;
880 static int subpixel
= -1;
883 if((ret
= LookupEntry(plfsz
)) != -1) return ret
;
886 entry
= glyphsetCache
+ ret
;
887 entry
->lfsz
= *plfsz
;
888 for( format
= 0; format
< AA_MAXVALUE
; format
++ ) {
889 assert( !entry
->format
[format
] );
892 if(antialias
&& plfsz
->lf
.lfQuality
!= NONANTIALIASED_QUALITY
)
894 if(hinter
== -1 || subpixel
== -1)
896 RASTERIZER_STATUS status
;
897 GetRasterizerCaps(&status
, sizeof(status
));
898 hinter
= status
.wFlags
& WINE_TT_HINTER_ENABLED
;
899 subpixel
= status
.wFlags
& WINE_TT_SUBPIXEL_RENDERING_ENABLED
;
902 switch (plfsz
->lf
.lfQuality
)
904 case ANTIALIASED_QUALITY
:
905 entry
->aa_default
= get_antialias_type( hdc
, FALSE
, hinter
);
906 return ret
; /* ignore further configuration */
907 case CLEARTYPE_QUALITY
:
908 case CLEARTYPE_NATURAL_QUALITY
:
909 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
911 case DEFAULT_QUALITY
:
915 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING
, 0, &font_smoothing
, 0) &&
918 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
921 entry
->aa_default
= AA_None
;
925 font_smoothing
= TRUE
; /* default to enabled */
926 #ifdef SONAME_LIBFONTCONFIG
927 if (fontconfig_installed
)
929 FcPattern
*match
, *pattern
;
931 char family
[LF_FACESIZE
* 4];
933 #if defined(__i386__) && defined(__GNUC__)
934 /* fontconfig generates floating point exceptions, mask them */
935 WORD cw
, default_cw
= 0x37f;
936 __asm__
__volatile__("fnstcw %0; fldcw %1" : "=m" (cw
) : "m" (default_cw
));
939 WideCharToMultiByte( CP_UTF8
, 0, plfsz
->lf
.lfFaceName
, -1, family
, sizeof(family
), NULL
, NULL
);
940 pattern
= pFcPatternCreate();
941 pFcPatternAddString( pattern
, FC_FAMILY
, (FcChar8
*)family
);
942 if (plfsz
->lf
.lfWeight
!= FW_DONTCARE
)
945 switch (plfsz
->lf
.lfWeight
)
947 case FW_THIN
: weight
= FC_WEIGHT_THIN
; break;
948 case FW_EXTRALIGHT
: weight
= FC_WEIGHT_EXTRALIGHT
; break;
949 case FW_LIGHT
: weight
= FC_WEIGHT_LIGHT
; break;
950 case FW_NORMAL
: weight
= FC_WEIGHT_NORMAL
; break;
951 case FW_MEDIUM
: weight
= FC_WEIGHT_MEDIUM
; break;
952 case FW_SEMIBOLD
: weight
= FC_WEIGHT_SEMIBOLD
; break;
953 case FW_BOLD
: weight
= FC_WEIGHT_BOLD
; break;
954 case FW_EXTRABOLD
: weight
= FC_WEIGHT_EXTRABOLD
; break;
955 case FW_HEAVY
: weight
= FC_WEIGHT_HEAVY
; break;
956 default: weight
= (plfsz
->lf
.lfWeight
- 80) / 4; break;
958 pFcPatternAddInteger( pattern
, FC_WEIGHT
, weight
);
960 pFcPatternAddInteger( pattern
, FC_SLANT
, plfsz
->lf
.lfItalic
? FC_SLANT_ITALIC
: FC_SLANT_ROMAN
);
961 pFcConfigSubstitute( NULL
, pattern
, FcMatchPattern
);
962 pFcDefaultSubstitute( pattern
);
963 if ((match
= pFcFontMatch( NULL
, pattern
, &result
)))
968 if (pFcPatternGetBool( match
, FC_ANTIALIAS
, 0, &antialias
) != FcResultMatch
)
970 if (pFcPatternGetInteger( match
, FC_RGBA
, 0, &rgba
) == FcResultMatch
)
973 if (pFcPatternGetString( match
, FC_FILE
, 0, &file
) != FcResultMatch
) file
= NULL
;
975 TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
976 rgba
, antialias
, debugstr_w(plfsz
->lf
.lfFaceName
), debugstr_a((char *)file
) );
980 case FC_RGBA_RGB
: entry
->aa_default
= AA_RGB
; break;
981 case FC_RGBA_BGR
: entry
->aa_default
= AA_BGR
; break;
982 case FC_RGBA_VRGB
: entry
->aa_default
= AA_VRGB
; break;
983 case FC_RGBA_VBGR
: entry
->aa_default
= AA_VBGR
; break;
984 case FC_RGBA_NONE
: entry
->aa_default
= AA_Grey
; break;
987 if (!antialias
) font_smoothing
= FALSE
;
988 pFcPatternDestroy( match
);
990 pFcPatternDestroy( pattern
);
992 #if defined(__i386__) && defined(__GNUC__)
993 __asm__
__volatile__("fnclex; fldcw %0" : : "m" (cw
));
996 #endif /* SONAME_LIBFONTCONFIG */
998 /* now check Xft resources */
1001 BOOL antialias
= TRUE
;
1004 if ((value
= XGetDefault( gdi_display
, "Xft", "antialias" )))
1006 if (tolower(value
[0]) == 'f' || tolower(value
[0]) == 'n' ||
1007 value
[0] == '0' || !strcasecmp( value
, "off" ))
1010 if ((value
= XGetDefault( gdi_display
, "Xft", "rgba" )))
1012 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value
, antialias
);
1013 if (!strcmp( value
, "rgb" )) entry
->aa_default
= AA_RGB
;
1014 else if (!strcmp( value
, "bgr" )) entry
->aa_default
= AA_BGR
;
1015 else if (!strcmp( value
, "vrgb" )) entry
->aa_default
= AA_VRGB
;
1016 else if (!strcmp( value
, "vbgr" )) entry
->aa_default
= AA_VBGR
;
1017 else if (!strcmp( value
, "none" )) entry
->aa_default
= AA_Grey
;
1019 wine_tsx11_unlock();
1020 if (!antialias
) font_smoothing
= FALSE
;
1023 if (!font_smoothing
) entry
->aa_default
= AA_None
;
1026 entry
->aa_default
= AA_None
;
1031 static void dec_ref_cache(int index
)
1034 TRACE("dec'ing entry %d to %d\n", index
, glyphsetCache
[index
].count
- 1);
1035 assert(glyphsetCache
[index
].count
> 0);
1036 glyphsetCache
[index
].count
--;
1039 static void lfsz_calc_hash(LFANDSIZE
*plfsz
)
1041 DWORD hash
= 0, *ptr
, two_chars
;
1045 hash
^= plfsz
->devsize
.cx
;
1046 hash
^= plfsz
->devsize
.cy
;
1047 for(i
= 0, ptr
= (DWORD
*)&plfsz
->xform
; i
< sizeof(XFORM
)/sizeof(DWORD
); i
++, ptr
++)
1049 for(i
= 0, ptr
= (DWORD
*)&plfsz
->lf
; i
< 7; i
++, ptr
++)
1051 for(i
= 0, ptr
= (DWORD
*)plfsz
->lf
.lfFaceName
; i
< LF_FACESIZE
/2; i
++, ptr
++) {
1053 pwc
= (WCHAR
*)&two_chars
;
1055 *pwc
= toupperW(*pwc
);
1057 *pwc
= toupperW(*pwc
);
1065 /***********************************************************************
1066 * X11DRV_XRender_Finalize
1068 void X11DRV_XRender_Finalize(void)
1072 EnterCriticalSection(&xrender_cs
);
1073 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
1075 LeaveCriticalSection(&xrender_cs
);
1076 DeleteCriticalSection(&xrender_cs
);
1079 /**********************************************************************
1080 * xrenderdrv_SelectFont
1082 static HFONT
xrenderdrv_SelectFont( PHYSDEV dev
, HFONT hfont
)
1085 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1086 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSelectFont
);
1087 HFONT ret
= next
->funcs
->pSelectFont( next
, hfont
);
1091 GetObjectW( hfont
, sizeof(lfsz
.lf
), &lfsz
.lf
);
1093 TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1094 lfsz
.lf
.lfHeight
, lfsz
.lf
.lfWidth
, lfsz
.lf
.lfWeight
,
1095 lfsz
.lf
.lfItalic
, lfsz
.lf
.lfCharSet
, debugstr_w(lfsz
.lf
.lfFaceName
));
1096 lfsz
.lf
.lfWidth
= abs( lfsz
.lf
.lfWidth
);
1097 lfsz
.devsize
.cx
= X11DRV_XWStoDS( dev
->hdc
, lfsz
.lf
.lfWidth
);
1098 lfsz
.devsize
.cy
= X11DRV_YWStoDS( dev
->hdc
, lfsz
.lf
.lfHeight
);
1100 GetTransform( dev
->hdc
, 0x204, &lfsz
.xform
);
1101 TRACE("font transform %f %f %f %f\n", lfsz
.xform
.eM11
, lfsz
.xform
.eM12
,
1102 lfsz
.xform
.eM21
, lfsz
.xform
.eM22
);
1104 if (GetGraphicsMode( dev
->hdc
) == GM_COMPATIBLE
&& lfsz
.xform
.eM11
* lfsz
.xform
.eM22
< 0)
1105 lfsz
.lf
.lfOrientation
= -lfsz
.lf
.lfOrientation
;
1107 /* Not used fields, would break hashing */
1108 lfsz
.xform
.eDx
= lfsz
.xform
.eDy
= 0;
1110 lfsz_calc_hash(&lfsz
);
1112 EnterCriticalSection(&xrender_cs
);
1113 if (physdev
->cache_index
!= -1)
1114 dec_ref_cache( physdev
->cache_index
);
1115 physdev
->cache_index
= GetCacheEntry( dev
->hdc
, &lfsz
);
1116 LeaveCriticalSection(&xrender_cs
);
1120 static BOOL
create_xrender_dc( PHYSDEV
*pdev
, enum wxr_format format
)
1122 X11DRV_PDEVICE
*x11dev
= get_x11drv_dev( *pdev
);
1123 struct xrender_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
1125 if (!physdev
) return FALSE
;
1126 physdev
->x11dev
= x11dev
;
1127 physdev
->cache_index
= -1;
1128 physdev
->format
= format
;
1129 physdev
->pict_format
= pict_formats
[format
];
1130 push_dc_driver( pdev
, &physdev
->dev
, &xrender_funcs
);
1134 /* store the color mask data in the bitmap info structure */
1135 static void set_color_info( XRenderPictFormat
*format
, BITMAPINFO
*info
)
1137 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1139 info
->bmiHeader
.biPlanes
= 1;
1140 info
->bmiHeader
.biBitCount
= pixmap_formats
[format
->depth
]->bits_per_pixel
;
1141 info
->bmiHeader
.biCompression
= BI_RGB
;
1142 info
->bmiHeader
.biClrUsed
= 0;
1144 switch (info
->bmiHeader
.biBitCount
)
1147 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1148 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1149 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1150 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1153 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1154 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1155 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1156 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1157 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1163 /**********************************************************************
1164 * xrenderdrv_CreateDC
1166 static BOOL
xrenderdrv_CreateDC( PHYSDEV
*pdev
, LPCWSTR driver
, LPCWSTR device
,
1167 LPCWSTR output
, const DEVMODEW
* initData
)
1169 return create_xrender_dc( pdev
, default_format
);
1172 /**********************************************************************
1173 * xrenderdrv_CreateCompatibleDC
1175 static BOOL
xrenderdrv_CreateCompatibleDC( PHYSDEV orig
, PHYSDEV
*pdev
)
1177 if (orig
) /* chain to x11drv first */
1179 orig
= GET_NEXT_PHYSDEV( orig
, pCreateCompatibleDC
);
1180 if (!orig
->funcs
->pCreateCompatibleDC( orig
, pdev
)) return FALSE
;
1182 /* otherwise we have been called by x11drv */
1184 return create_xrender_dc( pdev
, WXR_FORMAT_MONO
);
1187 /**********************************************************************
1188 * xrenderdrv_DeleteDC
1190 static BOOL
xrenderdrv_DeleteDC( PHYSDEV dev
)
1192 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1194 free_xrender_picture( physdev
);
1196 EnterCriticalSection( &xrender_cs
);
1197 if (physdev
->cache_index
!= -1) dec_ref_cache( physdev
->cache_index
);
1198 LeaveCriticalSection( &xrender_cs
);
1200 HeapFree( GetProcessHeap(), 0, physdev
);
1204 /**********************************************************************
1205 * xrenderdrv_ExtEscape
1207 static INT
xrenderdrv_ExtEscape( PHYSDEV dev
, INT escape
, INT in_count
, LPCVOID in_data
,
1208 INT out_count
, LPVOID out_data
)
1210 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1212 dev
= GET_NEXT_PHYSDEV( dev
, pExtEscape
);
1214 if (escape
== X11DRV_ESCAPE
&& in_data
&& in_count
>= sizeof(enum x11drv_escape_codes
))
1216 if (*(const enum x11drv_escape_codes
*)in_data
== X11DRV_SET_DRAWABLE
)
1218 BOOL ret
= dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1219 if (ret
) free_xrender_picture( physdev
); /* pict format doesn't change, only drawable */
1223 return dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1226 /***********************************************************************
1227 * xrenderdrv_SetDeviceClipping
1229 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
1231 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1233 physdev
->region
= rgn
;
1234 physdev
->update_clip
= TRUE
;
1236 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
1237 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
1241 /************************************************************************
1244 * Helper to ExtTextOut. Must be called inside xrender_cs
1246 static void UploadGlyph(struct xrender_physdev
*physDev
, int glyph
, AA_Type format
)
1248 unsigned int buflen
;
1253 gsCacheEntry
*entry
= glyphsetCache
+ physDev
->cache_index
;
1254 gsCacheEntryFormat
*formatEntry
;
1255 UINT ggo_format
= GGO_GLYPH_INDEX
;
1256 enum wxr_format wxr_format
;
1257 static const char zero
[4];
1258 static const MAT2 identity
= { {0,1},{0,0},{0,0},{0,1} };
1262 ggo_format
|= WINE_GGO_GRAY16_BITMAP
;
1265 ggo_format
|= WINE_GGO_HRGB_BITMAP
;
1268 ggo_format
|= WINE_GGO_HBGR_BITMAP
;
1271 ggo_format
|= WINE_GGO_VRGB_BITMAP
;
1274 ggo_format
|= WINE_GGO_VBGR_BITMAP
;
1278 ERR("aa = %d - not implemented\n", format
);
1280 ggo_format
|= GGO_BITMAP
;
1284 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1285 if(buflen
== GDI_ERROR
) {
1286 if(format
!= AA_None
) {
1288 entry
->aa_default
= AA_None
;
1289 ggo_format
= GGO_GLYPH_INDEX
| GGO_BITMAP
;
1290 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1292 if(buflen
== GDI_ERROR
) {
1293 WARN("GetGlyphOutlineW failed using default glyph\n");
1294 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0, ggo_format
, &gm
, 0, NULL
, &identity
);
1295 if(buflen
== GDI_ERROR
) {
1296 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1297 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0x20, ggo_format
, &gm
, 0, NULL
, &identity
);
1298 if(buflen
== GDI_ERROR
) {
1299 ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1304 TRACE("Turning off antialiasing for this monochrome font\n");
1307 /* If there is nothing for the current type, we create the entry. */
1308 if( !entry
->format
[format
] ) {
1309 entry
->format
[format
] = HeapAlloc(GetProcessHeap(),
1311 sizeof(gsCacheEntryFormat
));
1313 formatEntry
= entry
->format
[format
];
1315 if(formatEntry
->nrealized
<= glyph
) {
1316 formatEntry
->nrealized
= (glyph
/ 128 + 1) * 128;
1318 if (formatEntry
->realized
)
1319 formatEntry
->realized
= HeapReAlloc(GetProcessHeap(),
1321 formatEntry
->realized
,
1322 formatEntry
->nrealized
* sizeof(BOOL
));
1324 formatEntry
->realized
= HeapAlloc(GetProcessHeap(),
1326 formatEntry
->nrealized
* sizeof(BOOL
));
1328 if (formatEntry
->gis
)
1329 formatEntry
->gis
= HeapReAlloc(GetProcessHeap(),
1332 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1334 formatEntry
->gis
= HeapAlloc(GetProcessHeap(),
1336 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1340 if(formatEntry
->glyphset
== 0) {
1343 wxr_format
= WXR_FORMAT_GRAY
;
1350 wxr_format
= WXR_FORMAT_A8R8G8B8
;
1354 ERR("aa = %d - not implemented\n", format
);
1356 wxr_format
= WXR_FORMAT_MONO
;
1361 formatEntry
->font_format
= pict_formats
[wxr_format
];
1362 formatEntry
->glyphset
= pXRenderCreateGlyphSet(gdi_display
, formatEntry
->font_format
);
1363 wine_tsx11_unlock();
1367 buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buflen
);
1368 GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, buflen
, buf
, &identity
);
1369 formatEntry
->realized
[glyph
] = TRUE
;
1371 TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1373 gm
.gmBlackBoxX
, gm
.gmBlackBoxY
, gm
.gmCellIncX
, gm
.gmCellIncY
,
1374 gm
.gmptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.y
);
1376 gi
.width
= gm
.gmBlackBoxX
;
1377 gi
.height
= gm
.gmBlackBoxY
;
1378 gi
.x
= -gm
.gmptGlyphOrigin
.x
;
1379 gi
.y
= gm
.gmptGlyphOrigin
.y
;
1380 gi
.xOff
= gm
.gmCellIncX
;
1381 gi
.yOff
= gm
.gmCellIncY
;
1383 if(TRACE_ON(xrender
)) {
1386 unsigned char *line
;
1388 if(format
== AA_None
) {
1389 pitch
= ((gi
.width
+ 31) / 32) * 4;
1390 for(i
= 0; i
< gi
.height
; i
++) {
1391 line
= (unsigned char*) buf
+ i
* pitch
;
1393 for(j
= 0; j
< pitch
* 8; j
++) {
1394 strcat(output
, (line
[j
/ 8] & (1 << (7 - (j
% 8)))) ? "#" : " ");
1396 TRACE("%s\n", output
);
1399 static const char blks
[] = " .:;!o*#";
1403 pitch
= ((gi
.width
+ 3) / 4) * 4;
1404 for(i
= 0; i
< gi
.height
; i
++) {
1405 line
= (unsigned char*) buf
+ i
* pitch
;
1407 for(j
= 0; j
< pitch
; j
++) {
1408 str
[0] = blks
[line
[j
] >> 5];
1409 strcat(output
, str
);
1411 TRACE("%s\n", output
);
1417 if(formatEntry
->glyphset
) {
1418 if(format
== AA_None
&& BitmapBitOrder(gdi_display
) != MSBFirst
) {
1419 unsigned char *byte
= (unsigned char*) buf
, c
;
1425 /* magic to flip bit order */
1426 c
= ((c
<< 1) & 0xaa) | ((c
>> 1) & 0x55);
1427 c
= ((c
<< 2) & 0xcc) | ((c
>> 2) & 0x33);
1428 c
= ((c
<< 4) & 0xf0) | ((c
>> 4) & 0x0f);
1433 else if ( format
!= AA_Grey
&&
1434 ImageByteOrder (gdi_display
) != NATIVE_BYTE_ORDER
)
1436 unsigned int i
, *data
= (unsigned int *)buf
;
1437 for (i
= buflen
/ sizeof(int); i
; i
--, data
++) *data
= RtlUlongByteSwap(*data
);
1442 XRenderCompositeText seems to ignore 0x0 glyphs when
1443 AA_None, which means we lose the advance width of glyphs
1444 like the space. We'll pretend that such glyphs are 1x1
1449 gi
.width
= gi
.height
= 1;
1452 pXRenderAddGlyphs(gdi_display
, formatEntry
->glyphset
, &gid
, &gi
, 1,
1453 buflen
? buf
: zero
, buflen
? buflen
: sizeof(zero
));
1454 wine_tsx11_unlock();
1455 HeapFree(GetProcessHeap(), 0, buf
);
1458 formatEntry
->gis
[glyph
] = gi
;
1461 /*************************************************************
1464 * Returns an appropriate Picture for tiling the text colour.
1465 * Call and use result within the xrender_cs
1467 static Picture
get_tile_pict( enum wxr_format wxr_format
, const XRenderColor
*color
)
1473 XRenderColor current_color
;
1474 } tiles
[WXR_NB_FORMATS
], *tile
;
1476 tile
= &tiles
[wxr_format
];
1480 XRenderPictureAttributes pa
;
1481 XRenderPictFormat
*pict_format
= pict_formats
[wxr_format
];
1484 tile
->xpm
= XCreatePixmap(gdi_display
, root_window
, 1, 1, pict_format
->depth
);
1486 pa
.repeat
= RepeatNormal
;
1487 tile
->pict
= pXRenderCreatePicture(gdi_display
, tile
->xpm
, pict_format
, CPRepeat
, &pa
);
1488 wine_tsx11_unlock();
1490 /* init current_color to something different from text_pixel */
1491 tile
->current_color
= *color
;
1492 tile
->current_color
.red
^= 0xffff;
1494 if (wxr_format
== WXR_FORMAT_MONO
)
1496 /* for a 1bpp bitmap we always need a 1 in the tile */
1498 col
.red
= col
.green
= col
.blue
= 0;
1501 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, &col
, 0, 0, 1, 1);
1502 wine_tsx11_unlock();
1506 if (memcmp( color
, &tile
->current_color
, sizeof(*color
) ) && wxr_format
!= WXR_FORMAT_MONO
)
1509 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, color
, 0, 0, 1, 1);
1510 wine_tsx11_unlock();
1511 tile
->current_color
= *color
;
1516 /*************************************************************
1519 * Returns an appropriate Picture for masking with the specified alpha.
1520 * Call and use result within the xrender_cs
1522 static Picture
get_mask_pict( int alpha
)
1524 static Pixmap pixmap
;
1525 static Picture pict
;
1526 static int current_alpha
;
1528 if (alpha
== 0xffff) return 0; /* don't need a mask for alpha==1.0 */
1532 XRenderPictureAttributes pa
;
1535 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
1536 pa
.repeat
= RepeatNormal
;
1537 pict
= pXRenderCreatePicture( gdi_display
, pixmap
,
1538 pict_formats
[WXR_FORMAT_A8R8G8B8
], CPRepeat
, &pa
);
1539 wine_tsx11_unlock();
1543 if (alpha
!= current_alpha
)
1546 col
.red
= col
.green
= col
.blue
= 0;
1547 col
.alpha
= current_alpha
= alpha
;
1549 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
1550 wine_tsx11_unlock();
1555 /***********************************************************************
1556 * xrenderdrv_ExtTextOut
1558 static BOOL
xrenderdrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
,
1559 const RECT
*lprect
, LPCWSTR wstr
, UINT count
, const INT
*lpDx
)
1561 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1562 gsCacheEntry
*entry
;
1563 gsCacheEntryFormat
*formatEntry
;
1564 AA_Type aa_type
= AA_None
;
1566 Picture pict
, tile_pict
= 0;
1568 POINT offset
, desired
, current
;
1569 int render_op
= PictOpOver
;
1573 get_xrender_color( physdev
, GetTextColor( physdev
->dev
.hdc
), &col
);
1574 pict
= get_xrender_picture( physdev
, 0, (flags
& ETO_CLIPPED
) ? lprect
: NULL
);
1576 if(flags
& ETO_OPAQUE
)
1580 if (physdev
->format
== WXR_FORMAT_MONO
)
1581 /* use the inverse of the text color */
1582 bg
.red
= bg
.green
= bg
.blue
= bg
.alpha
= ~col
.alpha
;
1584 get_xrender_color( physdev
, GetBkColor( physdev
->dev
.hdc
), &bg
);
1587 set_xrender_transformation( pict
, 1, 1, 0, 0 );
1588 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &bg
,
1589 physdev
->x11dev
->dc_rect
.left
+ lprect
->left
,
1590 physdev
->x11dev
->dc_rect
.top
+ lprect
->top
,
1591 lprect
->right
- lprect
->left
,
1592 lprect
->bottom
- lprect
->top
);
1593 wine_tsx11_unlock();
1594 add_device_bounds( physdev
->x11dev
, lprect
);
1597 if(count
== 0) return TRUE
;
1599 EnterCriticalSection(&xrender_cs
);
1601 entry
= glyphsetCache
+ physdev
->cache_index
;
1602 aa_type
= entry
->aa_default
;
1603 formatEntry
= entry
->format
[aa_type
];
1605 for(idx
= 0; idx
< count
; idx
++) {
1606 if( !formatEntry
) {
1607 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
1608 /* re-evaluate antialias since aa_default may have changed */
1609 aa_type
= entry
->aa_default
;
1610 formatEntry
= entry
->format
[aa_type
];
1611 } else if( wstr
[idx
] >= formatEntry
->nrealized
|| formatEntry
->realized
[wstr
[idx
]] == FALSE
) {
1612 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
1617 WARN("could not upload requested glyphs\n");
1618 LeaveCriticalSection(&xrender_cs
);
1622 TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr
,count
),
1623 physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
1625 elts
= HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16
) * count
);
1627 /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
1628 So we pass zeros to the function and move to our starting position using the first
1629 element of the elts array. */
1631 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
;
1632 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
;
1633 offset
.x
= offset
.y
= 0;
1634 current
.x
= current
.y
= 0;
1636 tile_pict
= get_tile_pict(physdev
->format
, &col
);
1638 /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
1640 if (physdev
->format
== WXR_FORMAT_MONO
&& col
.red
== 0 && col
.green
== 0 && col
.blue
== 0)
1641 render_op
= PictOpOutReverse
; /* This gives us 'black' text */
1643 reset_bounds( &bounds
);
1644 for(idx
= 0; idx
< count
; idx
++)
1646 elts
[idx
].glyphset
= formatEntry
->glyphset
;
1647 elts
[idx
].chars
= wstr
+ idx
;
1648 elts
[idx
].nchars
= 1;
1649 elts
[idx
].xOff
= desired
.x
- current
.x
;
1650 elts
[idx
].yOff
= desired
.y
- current
.y
;
1652 current
.x
+= (elts
[idx
].xOff
+ formatEntry
->gis
[wstr
[idx
]].xOff
);
1653 current
.y
+= (elts
[idx
].yOff
+ formatEntry
->gis
[wstr
[idx
]].yOff
);
1655 rect
.left
= desired
.x
- physdev
->x11dev
->dc_rect
.left
- formatEntry
->gis
[wstr
[idx
]].x
;
1656 rect
.top
= desired
.y
- physdev
->x11dev
->dc_rect
.top
- formatEntry
->gis
[wstr
[idx
]].y
;
1657 rect
.right
= rect
.left
+ formatEntry
->gis
[wstr
[idx
]].width
;
1658 rect
.bottom
= rect
.top
+ formatEntry
->gis
[wstr
[idx
]].height
;
1659 add_bounds_rect( &bounds
, &rect
);
1663 desired
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
1664 desired
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
1670 offset
.x
+= lpDx
[idx
* 2];
1671 offset
.y
+= lpDx
[idx
* 2 + 1];
1674 offset
.x
+= lpDx
[idx
];
1675 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
;
1676 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
;
1681 /* Make sure we don't have any transforms set from a previous call */
1682 set_xrender_transformation(pict
, 1, 1, 0, 0);
1683 pXRenderCompositeText16(gdi_display
, render_op
,
1686 formatEntry
->font_format
,
1687 0, 0, 0, 0, elts
, count
);
1688 wine_tsx11_unlock();
1689 HeapFree(GetProcessHeap(), 0, elts
);
1691 LeaveCriticalSection(&xrender_cs
);
1692 add_device_bounds( physdev
->x11dev
, &bounds
);
1696 /* multiply the alpha channel of a picture */
1697 static void multiply_alpha( Picture pict
, XRenderPictFormat
*format
, int alpha
,
1698 int x
, int y
, int width
, int height
)
1700 XRenderPictureAttributes pa
;
1701 Pixmap src_pixmap
, mask_pixmap
;
1702 Picture src_pict
, mask_pict
;
1706 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
1707 mask_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
1708 pa
.repeat
= RepeatNormal
;
1709 src_pict
= pXRenderCreatePicture( gdi_display
, src_pixmap
, format
, CPRepeat
, &pa
);
1710 pa
.component_alpha
= True
;
1711 mask_pict
= pXRenderCreatePicture( gdi_display
, mask_pixmap
, format
, CPRepeat
|CPComponentAlpha
, &pa
);
1712 color
.red
= color
.green
= color
.blue
= color
.alpha
= 0xffff;
1713 pXRenderFillRectangle( gdi_display
, PictOpSrc
, src_pict
, &color
, 0, 0, 1, 1 );
1714 color
.alpha
= alpha
;
1715 pXRenderFillRectangle( gdi_display
, PictOpSrc
, mask_pict
, &color
, 0, 0, 1, 1 );
1716 pXRenderComposite( gdi_display
, PictOpInReverse
, src_pict
, mask_pict
, pict
,
1717 0, 0, 0, 0, x
, y
, width
, height
);
1718 pXRenderFreePicture( gdi_display
, src_pict
);
1719 pXRenderFreePicture( gdi_display
, mask_pict
);
1720 XFreePixmap( gdi_display
, src_pixmap
);
1721 XFreePixmap( gdi_display
, mask_pixmap
);
1722 wine_tsx11_unlock();
1725 /* Helper function for (stretched) blitting using xrender */
1726 static void xrender_blit( int op
, Picture src_pict
, Picture mask_pict
, Picture dst_pict
,
1727 int x_src
, int y_src
, int width_src
, int height_src
,
1728 int x_dst
, int y_dst
, int width_dst
, int height_dst
,
1729 double xscale
, double yscale
)
1731 int x_offset
, y_offset
;
1735 x_src
+= width_src
+ 1;
1736 width_src
= -width_src
;
1740 y_src
+= height_src
+ 1;
1741 height_src
= -height_src
;
1745 x_dst
+= width_dst
+ 1;
1746 width_dst
= -width_dst
;
1750 y_dst
+= height_dst
+ 1;
1751 height_dst
= -height_dst
;
1754 /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
1755 * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
1756 * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
1758 if(xscale
!= 1.0 || yscale
!= 1.0)
1760 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1761 * in the wrong quadrant of the x-y plane.
1763 x_offset
= (xscale
< 0) ? -width_dst
: 0;
1764 y_offset
= (yscale
< 0) ? -height_dst
: 0;
1765 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
1771 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
1773 pXRenderComposite( gdi_display
, op
, src_pict
, mask_pict
, dst_pict
,
1774 x_offset
, y_offset
, 0, 0, x_dst
, y_dst
, width_dst
, height_dst
);
1775 wine_tsx11_unlock();
1778 /* Helper function for (stretched) mono->color blitting using xrender */
1779 static void xrender_mono_blit( Picture src_pict
, Picture dst_pict
,
1780 enum wxr_format dst_format
, XRenderColor
*fg
, XRenderColor
*bg
,
1781 int x_src
, int y_src
, int width_src
, int height_src
,
1782 int x_dst
, int y_dst
, int width_dst
, int height_dst
,
1783 double xscale
, double yscale
)
1786 int x_offset
, y_offset
;
1791 x_src
+= width_src
+ 1;
1792 width_src
= -width_src
;
1796 y_src
+= height_src
+ 1;
1797 height_src
= -height_src
;
1801 x_dst
+= width_dst
+ 1;
1802 width_dst
= -width_dst
;
1806 y_dst
+= height_dst
+ 1;
1807 height_dst
= -height_dst
;
1810 /* When doing a mono->color blit, the source data is used as mask, and the source picture
1811 * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
1814 EnterCriticalSection( &xrender_cs
);
1816 color
.alpha
= 0xffff; /* tile pict needs 100% alpha */
1817 tile_pict
= get_tile_pict( dst_format
, &color
);
1820 pXRenderFillRectangle( gdi_display
, PictOpSrc
, dst_pict
, fg
, x_dst
, y_dst
, width_dst
, height_dst
);
1822 if (xscale
!= 1.0 || yscale
!= 1.0)
1824 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
1825 * in the wrong quadrant of the x-y plane.
1827 x_offset
= (xscale
< 0) ? -width_dst
: 0;
1828 y_offset
= (yscale
< 0) ? -height_dst
: 0;
1829 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
1835 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
1837 pXRenderComposite(gdi_display
, PictOpOver
, tile_pict
, src_pict
, dst_pict
,
1838 0, 0, x_offset
, y_offset
, x_dst
, y_dst
, width_dst
, height_dst
);
1839 wine_tsx11_unlock();
1840 LeaveCriticalSection( &xrender_cs
);
1842 /* force the alpha channel for background pixels, it has been set to 100% by the tile */
1843 if (bg
->alpha
!= 0xffff && (dst_format
== WXR_FORMAT_A8R8G8B8
|| dst_format
== WXR_FORMAT_B8G8R8A8
))
1844 multiply_alpha( dst_pict
, pict_formats
[dst_format
], bg
->alpha
,
1845 x_dst
, y_dst
, width_dst
, height_dst
);
1848 /* create a pixmap and render picture for an image */
1849 static DWORD
create_image_pixmap( BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
1850 struct bitblt_coords
*src
, enum wxr_format format
,
1851 Pixmap
*pixmap
, Picture
*pict
, BOOL
*use_repeat
)
1854 int width
= src
->visrect
.right
- src
->visrect
.left
;
1855 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
1856 int depth
= pict_formats
[format
]->depth
;
1857 struct gdi_image_bits dst_bits
;
1858 XRenderPictureAttributes pa
;
1863 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
1864 info
->bmiHeader
.biWidth
, height
, 32, 0 );
1865 wine_tsx11_unlock();
1866 if (!image
) return ERROR_OUTOFMEMORY
;
1868 ret
= copy_image_bits( info
, (format
== WXR_FORMAT_R8G8B8
), image
, bits
, &dst_bits
, src
, NULL
, ~0u );
1869 if (ret
) return ret
;
1871 image
->data
= dst_bits
.ptr
;
1873 *use_repeat
= (width
== 1 && height
== 1);
1874 pa
.repeat
= *use_repeat
? RepeatNormal
: RepeatNone
;
1877 *pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1878 gc
= XCreateGC( gdi_display
, *pixmap
, 0, NULL
);
1879 XPutImage( gdi_display
, *pixmap
, gc
, image
, src
->visrect
.left
, 0, 0, 0, width
, height
);
1880 *pict
= pXRenderCreatePicture( gdi_display
, *pixmap
, pict_formats
[format
], CPRepeat
, &pa
);
1881 XFreeGC( gdi_display
, gc
);
1882 wine_tsx11_unlock();
1884 /* make coordinates relative to the pixmap */
1885 src
->x
-= src
->visrect
.left
;
1886 src
->y
-= src
->visrect
.top
;
1887 OffsetRect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
1891 XDestroyImage( image
);
1892 wine_tsx11_unlock();
1893 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1897 static void xrender_stretch_blit( struct xrender_physdev
*physdev_src
, struct xrender_physdev
*physdev_dst
,
1898 Drawable drawable
, const struct bitblt_coords
*src
,
1899 const struct bitblt_coords
*dst
)
1902 Picture src_pict
= 0, dst_pict
, mask_pict
= 0;
1903 double xscale
= src
->width
/ (double)dst
->width
;
1904 double yscale
= src
->height
/ (double)dst
->height
;
1906 if (drawable
) /* using an intermediate pixmap */
1911 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, physdev_dst
->pict_format
, 0, NULL
);
1912 wine_tsx11_unlock();
1916 x_dst
= physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
;
1917 y_dst
= physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
;
1918 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
1921 src_pict
= get_xrender_picture_source( physdev_src
, FALSE
);
1924 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
1926 XRenderColor fg
, bg
;
1928 get_xrender_color( physdev_dst
, GetTextColor( physdev_dst
->dev
.hdc
), &fg
);
1929 get_xrender_color( physdev_dst
, GetBkColor( physdev_dst
->dev
.hdc
), &bg
);
1930 fg
.alpha
= bg
.alpha
= 0;
1932 xrender_mono_blit( src_pict
, dst_pict
, physdev_dst
->format
, &fg
, &bg
,
1933 physdev_src
->x11dev
->dc_rect
.left
+ src
->x
,
1934 physdev_src
->x11dev
->dc_rect
.top
+ src
->y
,
1935 src
->width
, src
->height
, x_dst
, y_dst
, dst
->width
, dst
->height
, xscale
, yscale
);
1937 else /* color -> color (can be at different depths) or mono -> mono */
1939 if (physdev_dst
->pict_format
->depth
== 32 && physdev_src
->pict_format
->depth
< 32)
1940 mask_pict
= get_no_alpha_mask();
1942 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
,
1943 physdev_src
->x11dev
->dc_rect
.left
+ src
->x
,
1944 physdev_src
->x11dev
->dc_rect
.top
+ src
->y
,
1945 src
->width
, src
->height
, x_dst
, y_dst
, dst
->width
, dst
->height
, xscale
, yscale
);
1951 pXRenderFreePicture( gdi_display
, dst_pict
);
1952 wine_tsx11_unlock();
1957 static void xrender_put_image( Pixmap src_pixmap
, Picture src_pict
, Picture mask_pict
, HRGN clip
,
1958 XRenderPictFormat
*dst_format
, struct xrender_physdev
*physdev
,
1959 Drawable drawable
, struct bitblt_coords
*src
,
1960 struct bitblt_coords
*dst
, BOOL use_repeat
)
1964 double xscale
, yscale
;
1966 if (drawable
) /* using an intermediate pixmap */
1968 RGNDATA
*clip_data
= NULL
;
1970 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
1974 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, dst_format
, 0, NULL
);
1976 pXRenderSetPictureClipRectangles( gdi_display
, dst_pict
, 0, 0,
1977 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
1978 wine_tsx11_unlock();
1979 HeapFree( GetProcessHeap(), 0, clip_data
);
1983 x_dst
= physdev
->x11dev
->dc_rect
.left
+ dst
->x
;
1984 y_dst
= physdev
->x11dev
->dc_rect
.top
+ dst
->y
;
1985 dst_pict
= get_xrender_picture( physdev
, clip
, &dst
->visrect
);
1990 xscale
= src
->width
/ (double)dst
->width
;
1991 yscale
= src
->height
/ (double)dst
->height
;
1993 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
1995 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
, src
->x
, src
->y
, src
->width
, src
->height
,
1996 x_dst
, y_dst
, dst
->width
, dst
->height
, xscale
, yscale
);
2001 pXRenderFreePicture( gdi_display
, dst_pict
);
2002 wine_tsx11_unlock();
2007 /***********************************************************************
2008 * xrenderdrv_StretchBlt
2010 static BOOL
xrenderdrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2011 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
2013 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2014 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2015 BOOL stretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
2017 if (src_dev
->funcs
!= dst_dev
->funcs
)
2019 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
2020 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
2023 /* XRender is of no use for color -> mono */
2024 if (physdev_dst
->format
== WXR_FORMAT_MONO
&& physdev_src
->format
!= WXR_FORMAT_MONO
)
2025 goto x11drv_fallback
;
2027 /* if not stretching, we only need to handle format conversion */
2028 if (!stretch
&& physdev_dst
->format
== physdev_src
->format
) goto x11drv_fallback
;
2034 struct bitblt_coords tmp
;
2036 /* make coordinates relative to tmp pixmap */
2038 tmp
.x
-= tmp
.visrect
.left
;
2039 tmp
.y
-= tmp
.visrect
.top
;
2040 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2043 tmpGC
= XCreateGC( gdi_display
, physdev_dst
->x11dev
->drawable
, 0, NULL
);
2044 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
2045 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
2046 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2047 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev_dst
->pict_format
->depth
);
2048 wine_tsx11_unlock();
2050 xrender_stretch_blit( physdev_src
, physdev_dst
, tmp_pixmap
, src
, &tmp
);
2051 execute_rop( physdev_dst
->x11dev
, tmp_pixmap
, tmpGC
, &dst
->visrect
, rop
);
2054 XFreePixmap( gdi_display
, tmp_pixmap
);
2055 XFreeGC( gdi_display
, tmpGC
);
2056 wine_tsx11_unlock();
2058 else xrender_stretch_blit( physdev_src
, physdev_dst
, 0, src
, dst
);
2060 add_device_bounds( physdev_dst
->x11dev
, &dst
->visrect
);
2064 return X11DRV_StretchBlt( &physdev_dst
->x11dev
->dev
, dst
, &physdev_src
->x11dev
->dev
, src
, rop
);
2068 /***********************************************************************
2069 * xrenderdrv_PutImage
2071 static DWORD
xrenderdrv_PutImage( PHYSDEV dev
, HRGN clip
, BITMAPINFO
*info
,
2072 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
2073 struct bitblt_coords
*dst
, DWORD rop
)
2075 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2079 enum wxr_format src_format
, dst_format
;
2080 XRenderPictFormat
*pict_format
;
2082 Picture src_pict
, mask_pict
= 0;
2085 dst_format
= physdev
->format
;
2086 src_format
= get_xrender_format_from_bitmapinfo( info
);
2087 if (!(pict_format
= pict_formats
[src_format
])) goto update_format
;
2089 /* make sure we can create an image with the same bpp */
2090 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2093 /* mono <-> color conversions not supported */
2094 if ((src_format
!= dst_format
) && (src_format
== WXR_FORMAT_MONO
|| dst_format
== WXR_FORMAT_MONO
))
2095 goto x11drv_fallback
;
2097 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2099 if (!has_alpha( src_format
) && has_alpha( dst_format
)) mask_pict
= get_no_alpha_mask();
2101 ret
= create_image_pixmap( info
, bits
, src
, src_format
, &src_pixmap
, &src_pict
, &use_repeat
);
2104 struct bitblt_coords tmp
;
2108 BOOL restore_region
= add_extra_clipping_region( physdev
->x11dev
, clip
);
2110 /* make coordinates relative to tmp pixmap */
2112 tmp
.x
-= tmp
.visrect
.left
;
2113 tmp
.y
-= tmp
.visrect
.top
;
2114 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2117 gc
= XCreateGC( gdi_display
, physdev
->x11dev
->drawable
, 0, NULL
);
2118 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
2119 XSetGraphicsExposures( gdi_display
, gc
, False
);
2120 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
,
2121 tmp
.visrect
.right
- tmp
.visrect
.left
,
2122 tmp
.visrect
.bottom
- tmp
.visrect
.top
,
2123 physdev
->pict_format
->depth
);
2124 wine_tsx11_unlock();
2126 xrender_put_image( src_pixmap
, src_pict
, mask_pict
, NULL
, physdev
->pict_format
,
2127 NULL
, tmp_pixmap
, src
, &tmp
, use_repeat
);
2128 execute_rop( physdev
->x11dev
, tmp_pixmap
, gc
, &dst
->visrect
, rop
);
2131 XFreePixmap( gdi_display
, tmp_pixmap
);
2132 XFreeGC( gdi_display
, gc
);
2133 wine_tsx11_unlock();
2135 if (restore_region
) restore_clipping_region( physdev
->x11dev
);
2137 else xrender_put_image( src_pixmap
, src_pict
, mask_pict
, clip
,
2138 physdev
->pict_format
, physdev
, 0, src
, dst
, use_repeat
);
2140 add_device_bounds( physdev
->x11dev
, &dst
->visrect
);
2143 pXRenderFreePicture( gdi_display
, src_pict
);
2144 XFreePixmap( gdi_display
, src_pixmap
);
2145 wine_tsx11_unlock();
2150 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2151 set_color_info( pict_formats
[dst_format
], info
);
2152 return ERROR_BAD_FORMAT
;
2155 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
2156 return dev
->funcs
->pPutImage( dev
, clip
, info
, bits
, src
, dst
, rop
);
2160 /***********************************************************************
2161 * xrenderdrv_BlendImage
2163 static DWORD
xrenderdrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2164 struct bitblt_coords
*src
, struct bitblt_coords
*dst
,
2165 BLENDFUNCTION func
)
2167 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2169 enum wxr_format format
;
2170 XRenderPictFormat
*pict_format
;
2171 Picture dst_pict
, src_pict
, mask_pict
;
2175 format
= get_xrender_format_from_bitmapinfo( info
);
2176 if (!(func
.AlphaFormat
& AC_SRC_ALPHA
))
2177 format
= get_format_without_alpha( format
);
2178 else if (format
!= WXR_FORMAT_A8R8G8B8
)
2179 return ERROR_INVALID_PARAMETER
;
2181 if (!(pict_format
= pict_formats
[format
])) goto update_format
;
2183 /* make sure we can create an image with the same bpp */
2184 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2187 if (format
== WXR_FORMAT_MONO
&& physdev
->format
!= WXR_FORMAT_MONO
)
2190 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2192 ret
= create_image_pixmap( info
, bits
, src
, format
, &src_pixmap
, &src_pict
, &use_repeat
);
2195 double xscale
, yscale
;
2199 xscale
= src
->width
/ (double)dst
->width
;
2200 yscale
= src
->height
/ (double)dst
->height
;
2202 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2204 dst_pict
= get_xrender_picture( physdev
, 0, &dst
->visrect
);
2206 EnterCriticalSection( &xrender_cs
);
2207 mask_pict
= get_mask_pict( func
.SourceConstantAlpha
* 257 );
2209 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
,
2210 src
->x
, src
->y
, src
->width
, src
->height
,
2211 physdev
->x11dev
->dc_rect
.left
+ dst
->x
,
2212 physdev
->x11dev
->dc_rect
.top
+ dst
->y
,
2213 dst
->width
, dst
->height
, xscale
, yscale
);
2216 pXRenderFreePicture( gdi_display
, src_pict
);
2217 XFreePixmap( gdi_display
, src_pixmap
);
2218 wine_tsx11_unlock();
2220 LeaveCriticalSection( &xrender_cs
);
2221 add_device_bounds( physdev
->x11dev
, &dst
->visrect
);
2226 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2227 set_color_info( physdev
->pict_format
, info
);
2228 return ERROR_BAD_FORMAT
;
2232 /***********************************************************************
2233 * xrenderdrv_AlphaBlend
2235 static BOOL
xrenderdrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2236 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION blendfn
)
2238 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2239 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2240 Picture dst_pict
, src_pict
= 0, mask_pict
= 0, tmp_pict
= 0;
2241 XRenderPictureAttributes pa
;
2242 Pixmap tmp_pixmap
= 0;
2243 double xscale
, yscale
;
2245 if (src_dev
->funcs
!= dst_dev
->funcs
)
2247 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
2248 return dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, blendfn
);
2251 if ((blendfn
.AlphaFormat
& AC_SRC_ALPHA
) && physdev_src
->format
!= WXR_FORMAT_A8R8G8B8
)
2253 SetLastError( ERROR_INVALID_PARAMETER
);
2257 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2259 xscale
= src
->width
/ (double)dst
->width
;
2260 yscale
= src
->height
/ (double)dst
->height
;
2262 src_pict
= get_xrender_picture_source( physdev_src
, FALSE
);
2264 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2266 /* mono -> color blending needs an intermediate color pixmap */
2267 XRenderColor fg
, bg
;
2268 int width
= src
->visrect
.right
- src
->visrect
.left
;
2269 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2271 /* blending doesn't use the destination DC colors */
2272 fg
.red
= fg
.green
= fg
.blue
= 0;
2273 bg
.red
= bg
.green
= bg
.blue
= 0xffff;
2274 fg
.alpha
= bg
.alpha
= 0xffff;
2277 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
,
2278 physdev_dst
->pict_format
->depth
);
2279 tmp_pict
= pXRenderCreatePicture( gdi_display
, tmp_pixmap
, physdev_dst
->pict_format
, 0, NULL
);
2280 wine_tsx11_unlock();
2282 xrender_mono_blit( src_pict
, tmp_pict
, physdev_dst
->format
, &fg
, &bg
,
2283 src
->visrect
.left
, src
->visrect
.top
, width
, height
, 0, 0, width
, height
, 1, 1 );
2285 else if (!(blendfn
.AlphaFormat
& AC_SRC_ALPHA
) && physdev_src
->pict_format
)
2287 /* we need a source picture with no alpha */
2288 enum wxr_format format
= get_format_without_alpha( physdev_src
->format
);
2289 if (format
!= physdev_src
->format
)
2292 pa
.subwindow_mode
= IncludeInferiors
;
2293 tmp_pict
= pXRenderCreatePicture( gdi_display
, physdev_src
->x11dev
->drawable
,
2294 pict_formats
[format
], CPSubwindowMode
, &pa
);
2295 wine_tsx11_unlock();
2299 if (tmp_pict
) src_pict
= tmp_pict
;
2301 EnterCriticalSection( &xrender_cs
);
2302 mask_pict
= get_mask_pict( blendfn
.SourceConstantAlpha
* 257 );
2304 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
,
2305 physdev_src
->x11dev
->dc_rect
.left
+ src
->x
,
2306 physdev_src
->x11dev
->dc_rect
.top
+ src
->y
,
2307 src
->width
, src
->height
,
2308 physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
,
2309 physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
,
2310 dst
->width
, dst
->height
, xscale
, yscale
);
2313 if (tmp_pict
) pXRenderFreePicture( gdi_display
, tmp_pict
);
2314 if (tmp_pixmap
) XFreePixmap( gdi_display
, tmp_pixmap
);
2315 wine_tsx11_unlock();
2317 LeaveCriticalSection( &xrender_cs
);
2318 add_device_bounds( physdev_dst
->x11dev
, &dst
->visrect
);
2322 /***********************************************************************
2323 * xrenderdrv_GradientFill
2325 static BOOL
xrenderdrv_GradientFill( PHYSDEV dev
, TRIVERTEX
*vert_array
, ULONG nvert
,
2326 void * grad_array
, ULONG ngrad
, ULONG mode
)
2328 #ifdef HAVE_XRENDERCREATELINEARGRADIENT
2329 static const XFixed stops
[2] = { 0, 1 << 16 };
2330 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2331 XLinearGradient gradient
;
2332 XRenderColor colors
[2];
2333 Picture src_pict
, dst_pict
;
2335 const GRADIENT_RECT
*rect
= grad_array
;
2339 if (!pXRenderCreateLinearGradient
) goto fallback
;
2341 /* <= 16-bpp uses dithering */
2342 if (!physdev
->pict_format
|| physdev
->pict_format
->depth
<= 16) goto fallback
;
2346 case GRADIENT_FILL_RECT_H
:
2347 case GRADIENT_FILL_RECT_V
:
2348 for (i
= 0; i
< ngrad
; i
++, rect
++)
2350 const TRIVERTEX
*v1
= vert_array
+ rect
->UpperLeft
;
2351 const TRIVERTEX
*v2
= vert_array
+ rect
->LowerRight
;
2353 colors
[0].red
= v1
->Red
* 257 / 256;
2354 colors
[0].green
= v1
->Green
* 257 / 256;
2355 colors
[0].blue
= v1
->Blue
* 257 / 256;
2356 colors
[1].red
= v2
->Red
* 257 / 256;
2357 colors
[1].green
= v2
->Green
* 257 / 256;
2358 colors
[1].blue
= v2
->Blue
* 257 / 256;
2359 /* always ignore alpha since otherwise xrender will want to pre-multiply the colors */
2360 colors
[0].alpha
= colors
[1].alpha
= 65535;
2366 LPtoDP( dev
->hdc
, pt
, 2 );
2367 if (mode
== GRADIENT_FILL_RECT_H
)
2369 gradient
.p1
.y
= gradient
.p2
.y
= 0;
2370 if (pt
[1].x
> pt
[0].x
)
2373 gradient
.p2
.x
= (pt
[1].x
- pt
[0].x
) << 16;
2377 gradient
.p1
.x
= (pt
[0].x
- pt
[1].x
) << 16;
2383 gradient
.p1
.x
= gradient
.p2
.x
= 0;
2384 if (pt
[1].y
> pt
[0].y
)
2387 gradient
.p2
.y
= (pt
[1].y
- pt
[0].y
) << 16;
2391 gradient
.p1
.y
= (pt
[0].y
- pt
[1].y
) << 16;
2396 rc
.left
= min( pt
[0].x
, pt
[1].x
);
2397 rc
.top
= min( pt
[0].y
, pt
[1].y
);
2398 rc
.right
= max( pt
[0].x
, pt
[1].x
);
2399 rc
.bottom
= max( pt
[0].y
, pt
[1].y
);
2401 TRACE( "%u gradient %s colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n",
2402 mode
, wine_dbgstr_rect( &rc
),
2403 colors
[0].red
, colors
[0].green
, colors
[0].blue
, colors
[0].alpha
,
2404 colors
[1].red
, colors
[1].green
, colors
[1].blue
, colors
[1].alpha
);
2406 dst_pict
= get_xrender_picture( physdev
, 0, NULL
);
2409 src_pict
= pXRenderCreateLinearGradient( gdi_display
, &gradient
, stops
, colors
, 2 );
2410 xrender_blit( PictOpSrc
, src_pict
, 0, dst_pict
,
2411 0, 0, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
2412 physdev
->x11dev
->dc_rect
.left
+ rc
.left
,
2413 physdev
->x11dev
->dc_rect
.top
+ rc
.top
,
2414 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, 1, 1 );
2415 pXRenderFreePicture( gdi_display
, src_pict
);
2416 wine_tsx11_unlock();
2417 add_device_bounds( physdev
->x11dev
, &rc
);
2424 dev
= GET_NEXT_PHYSDEV( dev
, pGradientFill
);
2425 return dev
->funcs
->pGradientFill( dev
, vert_array
, nvert
, grad_array
, ngrad
, mode
);
2428 /***********************************************************************
2429 * xrenderdrv_SelectBrush
2431 static HBRUSH
xrenderdrv_SelectBrush( PHYSDEV dev
, HBRUSH hbrush
, const struct brush_pattern
*pattern
)
2433 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2436 XRenderPictFormat
*format
= physdev
->pict_format
;
2438 if (!pattern
) goto x11drv_fallback
;
2439 if (pattern
->info
->bmiHeader
.biBitCount
== 1) goto x11drv_fallback
;
2440 if (physdev
->format
== WXR_FORMAT_MONO
) goto x11drv_fallback
;
2442 memset( &vis
, 0, sizeof(vis
) );
2443 vis
.depth
= format
->depth
;
2444 vis
.red_mask
= format
->direct
.redMask
<< format
->direct
.red
;
2445 vis
.green_mask
= format
->direct
.greenMask
<< format
->direct
.green
;
2446 vis
.blue_mask
= format
->direct
.blueMask
<< format
->direct
.blue
;
2448 pixmap
= create_pixmap_from_image( physdev
->dev
.hdc
, &vis
, pattern
->info
,
2449 &pattern
->bits
, pattern
->usage
);
2450 if (!pixmap
) return 0;
2453 if (physdev
->x11dev
->brush
.pixmap
) XFreePixmap( gdi_display
, physdev
->x11dev
->brush
.pixmap
);
2454 physdev
->x11dev
->brush
.pixmap
= pixmap
;
2455 physdev
->x11dev
->brush
.fillStyle
= FillTiled
;
2456 physdev
->x11dev
->brush
.pixel
= 0; /* ignored */
2457 physdev
->x11dev
->brush
.style
= BS_PATTERN
;
2458 wine_tsx11_unlock();
2462 dev
= GET_NEXT_PHYSDEV( dev
, pSelectBrush
);
2463 return dev
->funcs
->pSelectBrush( dev
, hbrush
, pattern
);
2467 static const struct gdi_dc_funcs xrender_funcs
=
2469 NULL
, /* pAbortDoc */
2470 NULL
, /* pAbortPath */
2471 xrenderdrv_AlphaBlend
, /* pAlphaBlend */
2472 NULL
, /* pAngleArc */
2475 NULL
, /* pBeginPath */
2476 xrenderdrv_BlendImage
, /* pBlendImage */
2478 NULL
, /* pCloseFigure */
2479 xrenderdrv_CreateCompatibleDC
, /* pCreateCompatibleDC */
2480 xrenderdrv_CreateDC
, /* pCreateDC */
2481 xrenderdrv_DeleteDC
, /* pDeleteDC */
2482 NULL
, /* pDeleteObject */
2483 NULL
, /* pDescribePixelFormat */
2484 NULL
, /* pDeviceCapabilities */
2485 NULL
, /* pEllipse */
2487 NULL
, /* pEndPage */
2488 NULL
, /* pEndPath */
2489 NULL
, /* pEnumFonts */
2490 NULL
, /* pEnumICMProfiles */
2491 NULL
, /* pExcludeClipRect */
2492 NULL
, /* pExtDeviceMode */
2493 xrenderdrv_ExtEscape
, /* pExtEscape */
2494 NULL
, /* pExtFloodFill */
2495 NULL
, /* pExtSelectClipRgn */
2496 xrenderdrv_ExtTextOut
, /* pExtTextOut */
2497 NULL
, /* pFillPath */
2498 NULL
, /* pFillRgn */
2499 NULL
, /* pFlattenPath */
2500 NULL
, /* pFontIsLinked */
2501 NULL
, /* pFrameRgn */
2502 NULL
, /* pGdiComment */
2503 NULL
, /* pGdiRealizationInfo */
2504 NULL
, /* pGetBoundsRect */
2505 NULL
, /* pGetCharABCWidths */
2506 NULL
, /* pGetCharABCWidthsI */
2507 NULL
, /* pGetCharWidth */
2508 NULL
, /* pGetDeviceCaps */
2509 NULL
, /* pGetDeviceGammaRamp */
2510 NULL
, /* pGetFontData */
2511 NULL
, /* pGetFontUnicodeRanges */
2512 NULL
, /* pGetGlyphIndices */
2513 NULL
, /* pGetGlyphOutline */
2514 NULL
, /* pGetICMProfile */
2515 NULL
, /* pGetImage */
2516 NULL
, /* pGetKerningPairs */
2517 NULL
, /* pGetNearestColor */
2518 NULL
, /* pGetOutlineTextMetrics */
2519 NULL
, /* pGetPixel */
2520 NULL
, /* pGetSystemPaletteEntries */
2521 NULL
, /* pGetTextCharsetInfo */
2522 NULL
, /* pGetTextExtentExPoint */
2523 NULL
, /* pGetTextExtentExPointI */
2524 NULL
, /* pGetTextFace */
2525 NULL
, /* pGetTextMetrics */
2526 xrenderdrv_GradientFill
, /* pGradientFill */
2527 NULL
, /* pIntersectClipRect */
2528 NULL
, /* pInvertRgn */
2530 NULL
, /* pModifyWorldTransform */
2532 NULL
, /* pOffsetClipRgn */
2533 NULL
, /* pOffsetViewportOrg */
2534 NULL
, /* pOffsetWindowOrg */
2535 NULL
, /* pPaintRgn */
2538 NULL
, /* pPolyBezier */
2539 NULL
, /* pPolyBezierTo */
2540 NULL
, /* pPolyDraw */
2541 NULL
, /* pPolyPolygon */
2542 NULL
, /* pPolyPolyline */
2543 NULL
, /* pPolygon */
2544 NULL
, /* pPolyline */
2545 NULL
, /* pPolylineTo */
2546 xrenderdrv_PutImage
, /* pPutImage */
2547 NULL
, /* pRealizeDefaultPalette */
2548 NULL
, /* pRealizePalette */
2549 NULL
, /* pRectangle */
2550 NULL
, /* pResetDC */
2551 NULL
, /* pRestoreDC */
2552 NULL
, /* pRoundRect */
2554 NULL
, /* pScaleViewportExt */
2555 NULL
, /* pScaleWindowExt */
2556 NULL
, /* pSelectBitmap */
2557 xrenderdrv_SelectBrush
, /* pSelectBrush */
2558 NULL
, /* pSelectClipPath */
2559 xrenderdrv_SelectFont
, /* pSelectFont */
2560 NULL
, /* pSelectPalette */
2561 NULL
, /* pSelectPen */
2562 NULL
, /* pSetArcDirection */
2563 NULL
, /* pSetBkColor */
2564 NULL
, /* pSetBkMode */
2565 NULL
, /* pSetBoundsRect */
2566 NULL
, /* pSetDCBrushColor */
2567 NULL
, /* pSetDCPenColor */
2568 NULL
, /* pSetDIBitsToDevice */
2569 xrenderdrv_SetDeviceClipping
, /* pSetDeviceClipping */
2570 NULL
, /* pSetDeviceGammaRamp */
2571 NULL
, /* pSetLayout */
2572 NULL
, /* pSetMapMode */
2573 NULL
, /* pSetMapperFlags */
2574 NULL
, /* pSetPixel */
2575 NULL
, /* pSetPixelFormat */
2576 NULL
, /* pSetPolyFillMode */
2577 NULL
, /* pSetROP2 */
2578 NULL
, /* pSetRelAbs */
2579 NULL
, /* pSetStretchBltMode */
2580 NULL
, /* pSetTextAlign */
2581 NULL
, /* pSetTextCharacterExtra */
2582 NULL
, /* pSetTextColor */
2583 NULL
, /* pSetTextJustification */
2584 NULL
, /* pSetViewportExt */
2585 NULL
, /* pSetViewportOrg */
2586 NULL
, /* pSetWindowExt */
2587 NULL
, /* pSetWindowOrg */
2588 NULL
, /* pSetWorldTransform */
2589 NULL
, /* pStartDoc */
2590 NULL
, /* pStartPage */
2591 xrenderdrv_StretchBlt
, /* pStretchBlt */
2592 NULL
, /* pStretchDIBits */
2593 NULL
, /* pStrokeAndFillPath */
2594 NULL
, /* pStrokePath */
2595 NULL
, /* pSwapBuffers */
2596 NULL
, /* pUnrealizePalette */
2597 NULL
, /* pWidenPath */
2598 NULL
, /* wine_get_wgl_driver */
2599 GDI_PRIORITY_GRAPHICS_DRV
+ 10 /* priority */
2602 #else /* SONAME_LIBXRENDER */
2604 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
2606 TRACE("XRender support not compiled in.\n");
2610 void X11DRV_XRender_Finalize(void)
2614 #endif /* SONAME_LIBXRENDER */