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 int using_client_side_fonts
= FALSE
;
43 WINE_DEFAULT_DEBUG_CHANNEL(xrender
);
45 #ifdef SONAME_LIBXRENDER
47 static BOOL X11DRV_XRender_Installed
= FALSE
;
50 #include <X11/extensions/Xrender.h>
52 #ifndef RepeatNone /* added in 0.10 */
54 #define RepeatNormal 1
56 #define RepeatReflect 3
74 WXR_INVALID_FORMAT
= WXR_NB_FORMATS
77 typedef struct wine_xrender_format_template
81 unsigned int alphaMask
;
85 unsigned int greenMask
;
87 unsigned int blueMask
;
88 } WineXRenderFormatTemplate
;
90 static const WineXRenderFormatTemplate wxr_formats_template
[WXR_NB_FORMATS
] =
92 /* Format depth alpha mask red mask green mask blue mask*/
93 /* WXR_FORMAT_MONO */ { 1, 0, 0x01, 0, 0, 0, 0, 0, 0 },
94 /* WXR_FORMAT_GRAY */ { 8, 0, 0xff, 0, 0, 0, 0, 0, 0 },
95 /* WXR_FORMAT_X1R5G5B5 */ { 16, 0, 0, 10, 0x1f, 5, 0x1f, 0, 0x1f },
96 /* WXR_FORMAT_X1B5G5R5 */ { 16, 0, 0, 0, 0x1f, 5, 0x1f, 10, 0x1f },
97 /* WXR_FORMAT_R5G6B5 */ { 16, 0, 0, 11, 0x1f, 5, 0x3f, 0, 0x1f },
98 /* WXR_FORMAT_B5G6R5 */ { 16, 0, 0, 0, 0x1f, 5, 0x3f, 11, 0x1f },
99 /* WXR_FORMAT_R8G8B8 */ { 24, 0, 0, 16, 0xff, 8, 0xff, 0, 0xff },
100 /* WXR_FORMAT_B8G8R8 */ { 24, 0, 0, 0, 0xff, 8, 0xff, 16, 0xff },
101 /* WXR_FORMAT_A8R8G8B8 */ { 32, 24, 0xff, 16, 0xff, 8, 0xff, 0, 0xff },
102 /* WXR_FORMAT_B8G8R8A8 */ { 32, 0, 0xff, 8, 0xff, 16, 0xff, 24, 0xff },
103 /* WXR_FORMAT_X8R8G8B8 */ { 32, 0, 0, 16, 0xff, 8, 0xff, 0, 0xff },
104 /* WXR_FORMAT_B8G8R8X8 */ { 32, 0, 0, 8, 0xff, 16, 0xff, 24, 0xff },
107 static const ColorShifts wxr_color_shifts
[WXR_NB_FORMATS
] =
109 /* format phys red phys green phys blue log red log green log blue */
110 /* WXR_FORMAT_MONO */ { { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 } },
111 /* WXR_FORMAT_GRAY */ { { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 }, { 0,0,0 } },
112 /* WXR_FORMAT_X1R5G5B5 */ { {10,5,31}, { 5,5,31}, { 0,5,31}, {10,5,31}, { 5,5,31}, { 0,5,31} },
113 /* WXR_FORMAT_X1B5G5R5 */ { { 0,5,31}, { 5,5,31}, {10,5,31}, { 0,5,31}, { 5,5,31}, {10,5,31} },
114 /* WXR_FORMAT_R5G6B5 */ { {11,5,31}, { 5,6,63}, { 0,5,31}, {11,5,31}, { 5,6,63}, { 0,5,31} },
115 /* WXR_FORMAT_B5G6R5 */ { { 0,5,31}, { 5,6,63}, {11,5,31}, { 0,5,31}, { 5,6,63}, {11,5,31} },
116 /* WXR_FORMAT_R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
117 /* WXR_FORMAT_B8G8R8 */ { { 0,8,255}, { 8,8,255}, {16,8,255}, { 0,8,255}, { 8,8,255}, {16,8,255} },
118 /* WXR_FORMAT_A8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
119 /* WXR_FORMAT_B8G8R8A8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
120 /* WXR_FORMAT_X8R8G8B8 */ { {16,8,255}, { 8,8,255}, { 0,8,255}, {16,8,255}, { 8,8,255}, { 0,8,255} },
121 /* WXR_FORMAT_B8G8R8X8 */ { { 8,8,255}, {16,8,255}, {24,8,255}, { 8,8,255}, {16,8,255}, {24,8,255} },
124 static enum wxr_format default_format
= WXR_INVALID_FORMAT
;
125 static XRenderPictFormat
*pict_formats
[WXR_NB_FORMATS
+ 1 /* invalid format */];
131 SIZE devsize
; /* size in device coords */
135 #define INITIAL_REALIZED_BUF_SIZE 128
137 typedef enum { AA_None
= 0, AA_Grey
, AA_RGB
, AA_BGR
, AA_VRGB
, AA_VBGR
, AA_MAXVALUE
} AA_Type
;
142 XRenderPictFormat
*font_format
;
147 } gsCacheEntryFormat
;
153 gsCacheEntryFormat
* format
[AA_MAXVALUE
];
158 struct xrender_physdev
160 struct gdi_physdev dev
;
161 X11DRV_PDEVICE
*x11dev
;
162 enum wxr_format format
;
167 XRenderPictFormat
*pict_format
;
170 static inline struct xrender_physdev
*get_xrender_dev( PHYSDEV dev
)
172 return (struct xrender_physdev
*)dev
;
175 static const struct gdi_dc_funcs xrender_funcs
;
177 static gsCacheEntry
*glyphsetCache
= NULL
;
178 static DWORD glyphsetCacheSize
= 0;
179 static INT lastfree
= -1;
182 #define INIT_CACHE_SIZE 10
184 static int antialias
= 1;
186 static void *xrender_handle
;
188 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
189 MAKE_FUNCPTR(XRenderAddGlyphs
)
190 MAKE_FUNCPTR(XRenderComposite
)
191 MAKE_FUNCPTR(XRenderCompositeText16
)
192 MAKE_FUNCPTR(XRenderCreateGlyphSet
)
193 MAKE_FUNCPTR(XRenderCreatePicture
)
194 MAKE_FUNCPTR(XRenderFillRectangle
)
195 MAKE_FUNCPTR(XRenderFindFormat
)
196 MAKE_FUNCPTR(XRenderFindVisualFormat
)
197 MAKE_FUNCPTR(XRenderFreeGlyphSet
)
198 MAKE_FUNCPTR(XRenderFreePicture
)
199 MAKE_FUNCPTR(XRenderSetPictureClipRectangles
)
200 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
201 MAKE_FUNCPTR(XRenderSetPictureTransform
)
203 MAKE_FUNCPTR(XRenderQueryExtension
)
205 #ifdef SONAME_LIBFONTCONFIG
206 #include <fontconfig/fontconfig.h>
207 MAKE_FUNCPTR(FcConfigSubstitute
)
208 MAKE_FUNCPTR(FcDefaultSubstitute
)
209 MAKE_FUNCPTR(FcFontMatch
)
211 MAKE_FUNCPTR(FcPatternCreate
)
212 MAKE_FUNCPTR(FcPatternDestroy
)
213 MAKE_FUNCPTR(FcPatternAddInteger
)
214 MAKE_FUNCPTR(FcPatternAddString
)
215 MAKE_FUNCPTR(FcPatternGetBool
)
216 MAKE_FUNCPTR(FcPatternGetInteger
)
217 MAKE_FUNCPTR(FcPatternGetString
)
218 static void *fontconfig_handle
;
219 static BOOL fontconfig_installed
;
224 static CRITICAL_SECTION xrender_cs
;
225 static CRITICAL_SECTION_DEBUG critsect_debug
=
228 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
229 0, 0, { (DWORD_PTR
)(__FILE__
": xrender_cs") }
231 static CRITICAL_SECTION xrender_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
233 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
234 ( ( (ULONG)_x4 << 24 ) | \
235 ( (ULONG)_x3 << 16 ) | \
236 ( (ULONG)_x2 << 8 ) | \
239 #define MS_GASP_TAG MS_MAKE_TAG('g', 'a', 's', 'p')
241 #define GASP_GRIDFIT 0x01
242 #define GASP_DOGRAY 0x02
244 #ifdef WORDS_BIGENDIAN
245 #define get_be_word(x) (x)
246 #define NATIVE_BYTE_ORDER MSBFirst
248 #define get_be_word(x) RtlUshortByteSwap(x)
249 #define NATIVE_BYTE_ORDER LSBFirst
252 static BOOL
has_alpha( enum wxr_format format
)
254 return (format
== WXR_FORMAT_A8R8G8B8
|| format
== WXR_FORMAT_B8G8R8A8
);
257 static enum wxr_format
get_format_without_alpha( enum wxr_format format
)
261 case WXR_FORMAT_A8R8G8B8
: return WXR_FORMAT_X8R8G8B8
;
262 case WXR_FORMAT_B8G8R8A8
: return WXR_FORMAT_B8G8R8X8
;
263 default: return format
;
267 static BOOL
get_xrender_template(const WineXRenderFormatTemplate
*fmt
, XRenderPictFormat
*templ
, unsigned long *mask
)
270 templ
->type
= PictTypeDirect
;
271 templ
->depth
= fmt
->depth
;
272 templ
->direct
.alpha
= fmt
->alpha
;
273 templ
->direct
.alphaMask
= fmt
->alphaMask
;
274 templ
->direct
.red
= fmt
->red
;
275 templ
->direct
.redMask
= fmt
->redMask
;
276 templ
->direct
.green
= fmt
->green
;
277 templ
->direct
.greenMask
= fmt
->greenMask
;
278 templ
->direct
.blue
= fmt
->blue
;
279 templ
->direct
.blueMask
= fmt
->blueMask
;
282 *mask
= PictFormatType
| PictFormatDepth
| PictFormatAlpha
| PictFormatAlphaMask
| PictFormatRed
| PictFormatRedMask
| PictFormatGreen
| PictFormatGreenMask
| PictFormatBlue
| PictFormatBlueMask
;
287 static BOOL
is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate
*fmt
)
289 if(fmt
->depth
!= screen_depth
)
291 if( (fmt
->redMask
<< fmt
->red
) != visual
->red_mask
)
293 if( (fmt
->greenMask
<< fmt
->green
) != visual
->green_mask
)
295 if( (fmt
->blueMask
<< fmt
->blue
) != visual
->blue_mask
)
298 /* We never select a default ARGB visual */
305 static int load_xrender_formats(void)
310 for (i
= 0; i
< WXR_NB_FORMATS
; i
++)
312 XRenderPictFormat templ
;
314 if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template
[i
]))
317 pict_formats
[i
] = pXRenderFindVisualFormat(gdi_display
, visual
);
318 if (!pict_formats
[i
])
320 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
321 if (visual
->class == DirectColor
)
324 if (XMatchVisualInfo( gdi_display
, DefaultScreen(gdi_display
),
325 screen_depth
, TrueColor
, &info
))
327 pict_formats
[i
] = pXRenderFindVisualFormat(gdi_display
, info
.visual
);
328 if (pict_formats
[i
]) visual
= info
.visual
;
333 if (pict_formats
[i
]) default_format
= i
;
337 unsigned long mask
= 0;
338 get_xrender_template(&wxr_formats_template
[i
], &templ
, &mask
);
341 pict_formats
[i
] = pXRenderFindFormat(gdi_display
, mask
, &templ
, 0);
347 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats
[i
]->id
, i
);
353 /***********************************************************************
354 * X11DRV_XRender_Init
356 * Let's see if our XServer has the extension available
359 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
363 if (client_side_with_render
&&
364 (xrender_handle
= wine_dlopen(SONAME_LIBXRENDER
, RTLD_NOW
, NULL
, 0)))
367 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
368 LOAD_FUNCPTR(XRenderAddGlyphs
)
369 LOAD_FUNCPTR(XRenderComposite
)
370 LOAD_FUNCPTR(XRenderCompositeText16
)
371 LOAD_FUNCPTR(XRenderCreateGlyphSet
)
372 LOAD_FUNCPTR(XRenderCreatePicture
)
373 LOAD_FUNCPTR(XRenderFillRectangle
)
374 LOAD_FUNCPTR(XRenderFindFormat
)
375 LOAD_FUNCPTR(XRenderFindVisualFormat
)
376 LOAD_FUNCPTR(XRenderFreeGlyphSet
)
377 LOAD_FUNCPTR(XRenderFreePicture
)
378 LOAD_FUNCPTR(XRenderSetPictureClipRectangles
)
379 LOAD_FUNCPTR(XRenderQueryExtension
)
381 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
382 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0);
383 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform
)
384 #undef LOAD_OPTIONAL_FUNCPTR
388 X11DRV_XRender_Installed
= pXRenderQueryExtension(gdi_display
, &event_base
, &xrender_error_base
);
390 if(X11DRV_XRender_Installed
) {
391 TRACE("Xrender is up and running error_base = %d\n", xrender_error_base
);
392 if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
396 "Wine has detected that you probably have a buggy version\n"
397 "of libXrender.so . Because of this client side font rendering\n"
398 "will be disabled. Please upgrade this library.\n");
399 X11DRV_XRender_Installed
= FALSE
;
403 if (!visual
->red_mask
|| !visual
->green_mask
|| !visual
->blue_mask
) {
404 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
405 X11DRV_XRender_Installed
= FALSE
;
410 #ifdef SONAME_LIBFONTCONFIG
411 if ((fontconfig_handle
= wine_dlopen(SONAME_LIBFONTCONFIG
, RTLD_NOW
, NULL
, 0)))
413 #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;}
414 LOAD_FUNCPTR(FcConfigSubstitute
);
415 LOAD_FUNCPTR(FcDefaultSubstitute
);
416 LOAD_FUNCPTR(FcFontMatch
);
417 LOAD_FUNCPTR(FcInit
);
418 LOAD_FUNCPTR(FcPatternCreate
);
419 LOAD_FUNCPTR(FcPatternDestroy
);
420 LOAD_FUNCPTR(FcPatternAddInteger
);
421 LOAD_FUNCPTR(FcPatternAddString
);
422 LOAD_FUNCPTR(FcPatternGetBool
);
423 LOAD_FUNCPTR(FcPatternGetInteger
);
424 LOAD_FUNCPTR(FcPatternGetString
);
426 fontconfig_installed
= pFcInit();
428 else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG
"\n" );
432 if(X11DRV_XRender_Installed
|| client_side_with_core
)
434 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
435 sizeof(*glyphsetCache
) * INIT_CACHE_SIZE
);
437 glyphsetCacheSize
= INIT_CACHE_SIZE
;
439 for(i
= 0; i
< INIT_CACHE_SIZE
; i
++) {
440 glyphsetCache
[i
].next
= i
+ 1;
441 glyphsetCache
[i
].count
= -1;
443 glyphsetCache
[i
-1].next
= -1;
444 using_client_side_fonts
= 1;
446 if(!X11DRV_XRender_Installed
) {
447 TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
448 if(screen_depth
<= 8 || !client_side_antialias_with_core
)
451 if(screen_depth
<= 8 || !client_side_antialias_with_render
)
454 return &xrender_funcs
;
456 TRACE("Using X11 core fonts\n");
460 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
461 static void get_xrender_color( XRenderPictFormat
*pf
, int src_color
, XRenderColor
*dst_color
)
463 if(pf
->direct
.redMask
)
464 dst_color
->red
= ((src_color
>> pf
->direct
.red
) & pf
->direct
.redMask
) * 65535/pf
->direct
.redMask
;
468 if(pf
->direct
.greenMask
)
469 dst_color
->green
= ((src_color
>> pf
->direct
.green
) & pf
->direct
.greenMask
) * 65535/pf
->direct
.greenMask
;
471 dst_color
->green
= 0;
473 if(pf
->direct
.blueMask
)
474 dst_color
->blue
= ((src_color
>> pf
->direct
.blue
) & pf
->direct
.blueMask
) * 65535/pf
->direct
.blueMask
;
478 dst_color
->alpha
= 0xffff;
481 static enum wxr_format
get_xrender_format_from_color_shifts(int depth
, ColorShifts
*shifts
)
483 int redMask
, greenMask
, blueMask
;
486 if (depth
== 1) return WXR_FORMAT_MONO
;
488 /* physDevs of a depth <=8, don't have color_shifts set and XRender can't handle those except for 1-bit */
489 if (!shifts
) return default_format
;
491 redMask
= shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
;
492 greenMask
= shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
;
493 blueMask
= shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
;
495 /* Try to locate a format which matches the specification of the dibsection. */
496 for(i
= 0; i
< WXR_NB_FORMATS
; i
++)
498 if( depth
== wxr_formats_template
[i
].depth
&&
499 redMask
== (wxr_formats_template
[i
].redMask
<< wxr_formats_template
[i
].red
) &&
500 greenMask
== (wxr_formats_template
[i
].greenMask
<< wxr_formats_template
[i
].green
) &&
501 blueMask
== (wxr_formats_template
[i
].blueMask
<< wxr_formats_template
[i
].blue
) )
505 /* This should not happen because when we reach 'shifts' must have been set and we only allows shifts which are backed by X */
506 ERR("No XRender format found for %u %08x/%08x/%08x\n", depth
, redMask
, greenMask
, blueMask
);
507 return WXR_INVALID_FORMAT
;
510 static enum wxr_format
get_xrender_format_from_bitmapinfo( const BITMAPINFO
*info
)
512 if (info
->bmiHeader
.biPlanes
!= 1) return WXR_INVALID_FORMAT
;
514 switch (info
->bmiHeader
.biBitCount
)
517 return WXR_FORMAT_MONO
;
522 if (info
->bmiHeader
.biCompression
!= BI_RGB
) break;
523 return WXR_FORMAT_R8G8B8
;
526 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
528 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
531 for (i
= 0; i
< WXR_NB_FORMATS
; i
++)
533 if (info
->bmiHeader
.biBitCount
== wxr_formats_template
[i
].depth
&&
534 colors
[0] == (wxr_formats_template
[i
].redMask
<< wxr_formats_template
[i
].red
) &&
535 colors
[1] == (wxr_formats_template
[i
].greenMask
<< wxr_formats_template
[i
].green
) &&
536 colors
[2] == (wxr_formats_template
[i
].blueMask
<< wxr_formats_template
[i
].blue
))
541 if (info
->bmiHeader
.biCompression
!= BI_RGB
) break;
542 return (info
->bmiHeader
.biBitCount
== 16) ? WXR_FORMAT_X1R5G5B5
: WXR_FORMAT_A8R8G8B8
;
544 return WXR_INVALID_FORMAT
;
547 static enum wxr_format
get_bitmap_format( int bpp
)
549 enum wxr_format format
= WXR_INVALID_FORMAT
;
551 if (bpp
== screen_bpp
)
555 case 16: format
= WXR_FORMAT_R5G6B5
; break;
556 case 24: format
= WXR_FORMAT_R8G8B8
; break;
557 case 32: format
= WXR_FORMAT_A8R8G8B8
; break;
563 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
564 static void set_xrender_transformation(Picture src_pict
, double xscale
, double yscale
, int xoffset
, int yoffset
)
566 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
567 XTransform xform
= {{
568 { XDoubleToFixed(xscale
), XDoubleToFixed(0), XDoubleToFixed(xoffset
) },
569 { XDoubleToFixed(0), XDoubleToFixed(yscale
), XDoubleToFixed(yoffset
) },
570 { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
573 pXRenderSetPictureTransform(gdi_display
, src_pict
, &xform
);
577 /* check if we can use repeating instead of scaling for the specified source DC */
578 static BOOL
use_source_repeat( struct xrender_physdev
*dev
)
580 return (dev
->x11dev
->bitmap
&&
581 dev
->x11dev
->drawable_rect
.right
- dev
->x11dev
->drawable_rect
.left
== 1 &&
582 dev
->x11dev
->drawable_rect
.bottom
- dev
->x11dev
->drawable_rect
.top
== 1);
585 static Picture
get_xrender_picture( struct xrender_physdev
*dev
, HRGN clip_rgn
, const RECT
*clip_rect
)
587 if (!dev
->pict
&& dev
->pict_format
)
589 XRenderPictureAttributes pa
;
592 pa
.subwindow_mode
= IncludeInferiors
;
593 dev
->pict
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
594 dev
->pict_format
, CPSubwindowMode
, &pa
);
596 TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
597 dev
->pict
, dev
->dev
.hdc
, dev
->x11dev
->drawable
);
598 dev
->update_clip
= TRUE
;
601 if (dev
->update_clip
)
608 rgn
= CreateRectRgnIndirect( clip_rect
);
609 if (clip_rgn
) CombineRgn( rgn
, rgn
, clip_rgn
, RGN_AND
);
610 CombineRgn( rgn
, rgn
, dev
->x11dev
->region
, RGN_AND
);
614 rgn
= CreateRectRgn( 0, 0, 0, 0 );
615 CombineRgn( rgn
, clip_rgn
, dev
->x11dev
->region
, RGN_AND
);
618 if ((clip_data
= X11DRV_GetRegionData( rgn
? rgn
: dev
->x11dev
->region
, 0 )))
621 pXRenderSetPictureClipRectangles( gdi_display
, dev
->pict
,
622 dev
->x11dev
->dc_rect
.left
, dev
->x11dev
->dc_rect
.top
,
623 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
625 HeapFree( GetProcessHeap(), 0, clip_data
);
627 dev
->update_clip
= (rgn
!= 0); /* have to update again if we are using a custom region */
628 if (rgn
) DeleteObject( rgn
);
633 static Picture
get_xrender_picture_source( struct xrender_physdev
*dev
, BOOL repeat
)
635 if (!dev
->pict_src
&& dev
->pict_format
)
637 XRenderPictureAttributes pa
;
640 pa
.subwindow_mode
= IncludeInferiors
;
641 pa
.repeat
= repeat
? RepeatNormal
: RepeatNone
;
642 dev
->pict_src
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
643 dev
->pict_format
, CPSubwindowMode
|CPRepeat
, &pa
);
646 TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
647 dev
->pict_src
, dev
->dev
.hdc
, dev
->x11dev
->drawable
, pa
.repeat
);
650 return dev
->pict_src
;
653 static void free_xrender_picture( struct xrender_physdev
*dev
)
655 if (dev
->pict
|| dev
->pict_src
)
658 XFlush( gdi_display
);
661 TRACE("freeing pict = %lx dc = %p\n", dev
->pict
, dev
->dev
.hdc
);
662 pXRenderFreePicture(gdi_display
, dev
->pict
);
667 TRACE("freeing pict = %lx dc = %p\n", dev
->pict_src
, dev
->dev
.hdc
);
668 pXRenderFreePicture(gdi_display
, dev
->pict_src
);
675 /* return a mask picture used to force alpha to 0 */
676 static Picture
get_no_alpha_mask(void)
678 static Pixmap pixmap
;
684 XRenderPictureAttributes pa
;
687 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
688 pa
.repeat
= RepeatNormal
;
689 pa
.component_alpha
= True
;
690 pict
= pXRenderCreatePicture( gdi_display
, pixmap
, pict_formats
[WXR_FORMAT_A8R8G8B8
],
691 CPRepeat
|CPComponentAlpha
, &pa
);
692 col
.red
= col
.green
= col
.blue
= 0xffff;
694 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
700 static BOOL
fontcmp(LFANDSIZE
*p1
, LFANDSIZE
*p2
)
702 if(p1
->hash
!= p2
->hash
) return TRUE
;
703 if(memcmp(&p1
->devsize
, &p2
->devsize
, sizeof(p1
->devsize
))) return TRUE
;
704 if(memcmp(&p1
->xform
, &p2
->xform
, sizeof(p1
->xform
))) return TRUE
;
705 if(memcmp(&p1
->lf
, &p2
->lf
, offsetof(LOGFONTW
, lfFaceName
))) return TRUE
;
706 return strcmpiW(p1
->lf
.lfFaceName
, p2
->lf
.lfFaceName
);
710 static void walk_cache(void)
714 EnterCriticalSection(&xrender_cs
);
715 for(i
=mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
716 TRACE("item %d\n", i
);
717 LeaveCriticalSection(&xrender_cs
);
721 static int LookupEntry(LFANDSIZE
*plfsz
)
725 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
727 if(glyphsetCache
[i
].count
== -1) break; /* reached free list so stop */
729 if(!fontcmp(&glyphsetCache
[i
].lfsz
, plfsz
)) {
730 glyphsetCache
[i
].count
++;
732 glyphsetCache
[prev_i
].next
= glyphsetCache
[i
].next
;
733 glyphsetCache
[i
].next
= mru
;
736 TRACE("found font in cache %d\n", i
);
741 TRACE("font not in cache\n");
745 static void FreeEntry(int entry
)
749 for(format
= 0; format
< AA_MAXVALUE
; format
++) {
750 gsCacheEntryFormat
* formatEntry
;
752 if( !glyphsetCache
[entry
].format
[format
] )
755 formatEntry
= glyphsetCache
[entry
].format
[format
];
757 if(formatEntry
->glyphset
) {
759 pXRenderFreeGlyphSet(gdi_display
, formatEntry
->glyphset
);
761 formatEntry
->glyphset
= 0;
763 if(formatEntry
->nrealized
) {
764 HeapFree(GetProcessHeap(), 0, formatEntry
->realized
);
765 formatEntry
->realized
= NULL
;
766 if(formatEntry
->bitmaps
) {
767 for(i
= 0; i
< formatEntry
->nrealized
; i
++)
768 HeapFree(GetProcessHeap(), 0, formatEntry
->bitmaps
[i
]);
769 HeapFree(GetProcessHeap(), 0, formatEntry
->bitmaps
);
770 formatEntry
->bitmaps
= NULL
;
772 HeapFree(GetProcessHeap(), 0, formatEntry
->gis
);
773 formatEntry
->gis
= NULL
;
774 formatEntry
->nrealized
= 0;
777 HeapFree(GetProcessHeap(), 0, formatEntry
);
778 glyphsetCache
[entry
].format
[format
] = NULL
;
782 static int AllocEntry(void)
784 int best
= -1, prev_best
= -1, i
, prev_i
= -1;
787 assert(glyphsetCache
[lastfree
].count
== -1);
788 glyphsetCache
[lastfree
].count
= 1;
790 lastfree
= glyphsetCache
[lastfree
].next
;
792 glyphsetCache
[best
].next
= mru
;
795 TRACE("empty space at %d, next lastfree = %d\n", mru
, lastfree
);
799 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
800 if(glyphsetCache
[i
].count
== 0) {
808 TRACE("freeing unused glyphset at cache %d\n", best
);
810 glyphsetCache
[best
].count
= 1;
812 glyphsetCache
[prev_best
].next
= glyphsetCache
[best
].next
;
813 glyphsetCache
[best
].next
= mru
;
821 TRACE("Growing cache\n");
824 glyphsetCache
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
826 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
827 * sizeof(*glyphsetCache
));
829 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
830 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
831 * sizeof(*glyphsetCache
));
833 for(best
= i
= glyphsetCacheSize
; i
< glyphsetCacheSize
+ INIT_CACHE_SIZE
;
835 glyphsetCache
[i
].next
= i
+ 1;
836 glyphsetCache
[i
].count
= -1;
838 glyphsetCache
[i
-1].next
= -1;
839 glyphsetCacheSize
+= INIT_CACHE_SIZE
;
841 lastfree
= glyphsetCache
[best
].next
;
842 glyphsetCache
[best
].count
= 1;
843 glyphsetCache
[best
].next
= mru
;
845 TRACE("new free cache slot at %d\n", mru
);
849 static BOOL
get_gasp_flags(HDC hdc
, WORD
*flags
)
859 size
= GetFontData(hdc
, MS_GASP_TAG
, 0, NULL
, 0);
860 if(size
== GDI_ERROR
)
863 gasp
= buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
864 GetFontData(hdc
, MS_GASP_TAG
, 0, gasp
, size
);
866 GetTextMetricsW(hdc
, &tm
);
867 ppem
= abs(X11DRV_YWStoDS(hdc
, tm
.tmAscent
+ tm
.tmDescent
- tm
.tmInternalLeading
));
870 num_recs
= get_be_word(*gasp
);
874 *flags
= get_be_word(*(gasp
+ 1));
875 if(ppem
<= get_be_word(*gasp
))
879 TRACE("got flags %04x for ppem %d\n", *flags
, ppem
);
881 HeapFree(GetProcessHeap(), 0, buffer
);
885 static AA_Type
get_antialias_type( HDC hdc
, BOOL subpixel
, BOOL hinter
)
889 UINT font_smoothing_type
, font_smoothing_orientation
;
891 if (X11DRV_XRender_Installed
&& subpixel
&&
892 SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE
, 0, &font_smoothing_type
, 0) &&
893 font_smoothing_type
== FE_FONTSMOOTHINGCLEARTYPE
)
895 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION
, 0,
896 &font_smoothing_orientation
, 0) &&
897 font_smoothing_orientation
== FE_FONTSMOOTHINGORIENTATIONBGR
)
904 If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
905 But, Wine's subpixel rendering can support the portrait mode.
908 else if (!hinter
|| !get_gasp_flags(hdc
, &flags
) || flags
& GASP_DOGRAY
)
916 static int GetCacheEntry( HDC hdc
, LFANDSIZE
*plfsz
)
921 static int hinter
= -1;
922 static int subpixel
= -1;
925 if((ret
= LookupEntry(plfsz
)) != -1) return ret
;
928 entry
= glyphsetCache
+ ret
;
929 entry
->lfsz
= *plfsz
;
930 for( format
= 0; format
< AA_MAXVALUE
; format
++ ) {
931 assert( !entry
->format
[format
] );
934 if(antialias
&& plfsz
->lf
.lfQuality
!= NONANTIALIASED_QUALITY
)
936 if(hinter
== -1 || subpixel
== -1)
938 RASTERIZER_STATUS status
;
939 GetRasterizerCaps(&status
, sizeof(status
));
940 hinter
= status
.wFlags
& WINE_TT_HINTER_ENABLED
;
941 subpixel
= status
.wFlags
& WINE_TT_SUBPIXEL_RENDERING_ENABLED
;
944 switch (plfsz
->lf
.lfQuality
)
946 case ANTIALIASED_QUALITY
:
947 entry
->aa_default
= get_antialias_type( hdc
, FALSE
, hinter
);
948 return ret
; /* ignore further configuration */
949 case CLEARTYPE_QUALITY
:
950 case CLEARTYPE_NATURAL_QUALITY
:
951 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
953 case DEFAULT_QUALITY
:
957 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING
, 0, &font_smoothing
, 0) &&
960 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
963 entry
->aa_default
= AA_None
;
967 font_smoothing
= TRUE
; /* default to enabled */
968 #ifdef SONAME_LIBFONTCONFIG
969 if (fontconfig_installed
)
971 FcPattern
*match
, *pattern
;
973 char family
[LF_FACESIZE
* 4];
975 #if defined(__i386__) && defined(__GNUC__)
976 /* fontconfig generates floating point exceptions, mask them */
977 WORD cw
, default_cw
= 0x37f;
978 __asm__
__volatile__("fnstcw %0; fldcw %1" : "=m" (cw
) : "m" (default_cw
));
981 WideCharToMultiByte( CP_UTF8
, 0, plfsz
->lf
.lfFaceName
, -1, family
, sizeof(family
), NULL
, NULL
);
982 pattern
= pFcPatternCreate();
983 pFcPatternAddString( pattern
, FC_FAMILY
, (FcChar8
*)family
);
984 if (plfsz
->lf
.lfWeight
!= FW_DONTCARE
)
987 switch (plfsz
->lf
.lfWeight
)
989 case FW_THIN
: weight
= FC_WEIGHT_THIN
; break;
990 case FW_EXTRALIGHT
: weight
= FC_WEIGHT_EXTRALIGHT
; break;
991 case FW_LIGHT
: weight
= FC_WEIGHT_LIGHT
; break;
992 case FW_NORMAL
: weight
= FC_WEIGHT_NORMAL
; break;
993 case FW_MEDIUM
: weight
= FC_WEIGHT_MEDIUM
; break;
994 case FW_SEMIBOLD
: weight
= FC_WEIGHT_SEMIBOLD
; break;
995 case FW_BOLD
: weight
= FC_WEIGHT_BOLD
; break;
996 case FW_EXTRABOLD
: weight
= FC_WEIGHT_EXTRABOLD
; break;
997 case FW_HEAVY
: weight
= FC_WEIGHT_HEAVY
; break;
998 default: weight
= (plfsz
->lf
.lfWeight
- 80) / 4; break;
1000 pFcPatternAddInteger( pattern
, FC_WEIGHT
, weight
);
1002 pFcPatternAddInteger( pattern
, FC_SLANT
, plfsz
->lf
.lfItalic
? FC_SLANT_ITALIC
: FC_SLANT_ROMAN
);
1003 pFcConfigSubstitute( NULL
, pattern
, FcMatchPattern
);
1004 pFcDefaultSubstitute( pattern
);
1005 if ((match
= pFcFontMatch( NULL
, pattern
, &result
)))
1010 if (pFcPatternGetBool( match
, FC_ANTIALIAS
, 0, &antialias
) != FcResultMatch
)
1012 if (pFcPatternGetInteger( match
, FC_RGBA
, 0, &rgba
) == FcResultMatch
)
1015 if (pFcPatternGetString( match
, FC_FILE
, 0, &file
) != FcResultMatch
) file
= NULL
;
1017 TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
1018 rgba
, antialias
, debugstr_w(plfsz
->lf
.lfFaceName
), debugstr_a((char *)file
) );
1022 case FC_RGBA_RGB
: entry
->aa_default
= AA_RGB
; break;
1023 case FC_RGBA_BGR
: entry
->aa_default
= AA_BGR
; break;
1024 case FC_RGBA_VRGB
: entry
->aa_default
= AA_VRGB
; break;
1025 case FC_RGBA_VBGR
: entry
->aa_default
= AA_VBGR
; break;
1026 case FC_RGBA_NONE
: entry
->aa_default
= AA_Grey
; break;
1029 if (!antialias
) font_smoothing
= FALSE
;
1030 pFcPatternDestroy( match
);
1032 pFcPatternDestroy( pattern
);
1034 #if defined(__i386__) && defined(__GNUC__)
1035 __asm__
__volatile__("fnclex; fldcw %0" : : "m" (cw
));
1038 #endif /* SONAME_LIBFONTCONFIG */
1040 /* now check Xft resources */
1043 BOOL antialias
= TRUE
;
1046 if ((value
= XGetDefault( gdi_display
, "Xft", "antialias" )))
1048 if (tolower(value
[0]) == 'f' || tolower(value
[0]) == 'n' ||
1049 value
[0] == '0' || !strcasecmp( value
, "off" ))
1052 if ((value
= XGetDefault( gdi_display
, "Xft", "rgba" )))
1054 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value
, antialias
);
1055 if (!strcmp( value
, "rgb" )) entry
->aa_default
= AA_RGB
;
1056 else if (!strcmp( value
, "bgr" )) entry
->aa_default
= AA_BGR
;
1057 else if (!strcmp( value
, "vrgb" )) entry
->aa_default
= AA_VRGB
;
1058 else if (!strcmp( value
, "vbgr" )) entry
->aa_default
= AA_VBGR
;
1059 else if (!strcmp( value
, "none" )) entry
->aa_default
= AA_Grey
;
1061 wine_tsx11_unlock();
1062 if (!antialias
) font_smoothing
= FALSE
;
1065 if (!font_smoothing
) entry
->aa_default
= AA_None
;
1067 /* we can't support subpixel without xrender */
1068 if (!X11DRV_XRender_Installed
&& entry
->aa_default
> AA_Grey
) entry
->aa_default
= AA_Grey
;
1071 entry
->aa_default
= AA_None
;
1076 static void dec_ref_cache(int index
)
1079 TRACE("dec'ing entry %d to %d\n", index
, glyphsetCache
[index
].count
- 1);
1080 assert(glyphsetCache
[index
].count
> 0);
1081 glyphsetCache
[index
].count
--;
1084 static void lfsz_calc_hash(LFANDSIZE
*plfsz
)
1086 DWORD hash
= 0, *ptr
, two_chars
;
1090 hash
^= plfsz
->devsize
.cx
;
1091 hash
^= plfsz
->devsize
.cy
;
1092 for(i
= 0, ptr
= (DWORD
*)&plfsz
->xform
; i
< sizeof(XFORM
)/sizeof(DWORD
); i
++, ptr
++)
1094 for(i
= 0, ptr
= (DWORD
*)&plfsz
->lf
; i
< 7; i
++, ptr
++)
1096 for(i
= 0, ptr
= (DWORD
*)plfsz
->lf
.lfFaceName
; i
< LF_FACESIZE
/2; i
++, ptr
++) {
1098 pwc
= (WCHAR
*)&two_chars
;
1100 *pwc
= toupperW(*pwc
);
1102 *pwc
= toupperW(*pwc
);
1110 /***********************************************************************
1111 * X11DRV_XRender_Finalize
1113 void X11DRV_XRender_Finalize(void)
1117 EnterCriticalSection(&xrender_cs
);
1118 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
1120 LeaveCriticalSection(&xrender_cs
);
1123 /**********************************************************************
1124 * xrenderdrv_SelectFont
1126 static HFONT
xrenderdrv_SelectFont( PHYSDEV dev
, HFONT hfont
)
1128 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1129 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSelectFont
);
1130 HFONT ret
= next
->funcs
->pSelectFont( next
, hfont
);
1134 if (physdev
->x11dev
->has_gdi_font
)
1138 GetObjectW( hfont
, sizeof(lfsz
.lf
), &lfsz
.lf
);
1140 TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1141 lfsz
.lf
.lfHeight
, lfsz
.lf
.lfWidth
, lfsz
.lf
.lfWeight
,
1142 lfsz
.lf
.lfItalic
, lfsz
.lf
.lfCharSet
, debugstr_w(lfsz
.lf
.lfFaceName
));
1143 lfsz
.lf
.lfWidth
= abs( lfsz
.lf
.lfWidth
);
1144 lfsz
.devsize
.cx
= X11DRV_XWStoDS( dev
->hdc
, lfsz
.lf
.lfWidth
);
1145 lfsz
.devsize
.cy
= X11DRV_YWStoDS( dev
->hdc
, lfsz
.lf
.lfHeight
);
1147 GetTransform( dev
->hdc
, 0x204, &lfsz
.xform
);
1148 TRACE("font transform %f %f %f %f\n", lfsz
.xform
.eM11
, lfsz
.xform
.eM12
,
1149 lfsz
.xform
.eM21
, lfsz
.xform
.eM22
);
1151 /* Not used fields, would break hashing */
1152 lfsz
.xform
.eDx
= lfsz
.xform
.eDy
= 0;
1154 lfsz_calc_hash(&lfsz
);
1156 EnterCriticalSection(&xrender_cs
);
1157 if (physdev
->cache_index
!= -1)
1158 dec_ref_cache( physdev
->cache_index
);
1159 physdev
->cache_index
= GetCacheEntry( dev
->hdc
, &lfsz
);
1160 LeaveCriticalSection(&xrender_cs
);
1164 EnterCriticalSection( &xrender_cs
);
1165 if (physdev
->cache_index
!= -1) dec_ref_cache( physdev
->cache_index
);
1166 physdev
->cache_index
= -1;
1167 LeaveCriticalSection( &xrender_cs
);
1172 static BOOL
create_xrender_dc( PHYSDEV
*pdev
, enum wxr_format format
)
1174 X11DRV_PDEVICE
*x11dev
= get_x11drv_dev( *pdev
);
1175 struct xrender_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
1177 if (!physdev
) return FALSE
;
1178 physdev
->x11dev
= x11dev
;
1179 physdev
->cache_index
= -1;
1180 physdev
->format
= format
;
1181 physdev
->pict_format
= pict_formats
[format
];
1182 push_dc_driver( pdev
, &physdev
->dev
, &xrender_funcs
);
1186 /* store the color mask data in the bitmap info structure */
1187 static void set_color_info( XRenderPictFormat
*format
, BITMAPINFO
*info
)
1189 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1191 info
->bmiHeader
.biPlanes
= 1;
1192 info
->bmiHeader
.biBitCount
= pixmap_formats
[format
->depth
]->bits_per_pixel
;
1193 info
->bmiHeader
.biCompression
= BI_RGB
;
1194 info
->bmiHeader
.biClrUsed
= 0;
1196 switch (info
->bmiHeader
.biBitCount
)
1199 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1200 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1201 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1202 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1205 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1206 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1207 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1208 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1209 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1215 /**********************************************************************
1216 * xrenderdrv_CreateDC
1218 static BOOL
xrenderdrv_CreateDC( PHYSDEV
*pdev
, LPCWSTR driver
, LPCWSTR device
,
1219 LPCWSTR output
, const DEVMODEW
* initData
)
1221 return create_xrender_dc( pdev
, default_format
);
1224 /**********************************************************************
1225 * xrenderdrv_CreateCompatibleDC
1227 static BOOL
xrenderdrv_CreateCompatibleDC( PHYSDEV orig
, PHYSDEV
*pdev
)
1229 if (orig
) /* chain to x11drv first */
1231 orig
= GET_NEXT_PHYSDEV( orig
, pCreateCompatibleDC
);
1232 if (!orig
->funcs
->pCreateCompatibleDC( orig
, pdev
)) return FALSE
;
1234 /* otherwise we have been called by x11drv */
1236 return create_xrender_dc( pdev
, WXR_FORMAT_MONO
);
1239 /**********************************************************************
1240 * xrenderdrv_DeleteDC
1242 static BOOL
xrenderdrv_DeleteDC( PHYSDEV dev
)
1244 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1246 free_xrender_picture( physdev
);
1248 EnterCriticalSection( &xrender_cs
);
1249 if (physdev
->cache_index
!= -1) dec_ref_cache( physdev
->cache_index
);
1250 LeaveCriticalSection( &xrender_cs
);
1252 HeapFree( GetProcessHeap(), 0, physdev
);
1256 /**********************************************************************
1257 * xrenderdrv_ExtEscape
1259 static INT
xrenderdrv_ExtEscape( PHYSDEV dev
, INT escape
, INT in_count
, LPCVOID in_data
,
1260 INT out_count
, LPVOID out_data
)
1262 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1264 dev
= GET_NEXT_PHYSDEV( dev
, pExtEscape
);
1266 if (escape
== X11DRV_ESCAPE
&& in_data
&& in_count
>= sizeof(enum x11drv_escape_codes
))
1268 if (*(const enum x11drv_escape_codes
*)in_data
== X11DRV_SET_DRAWABLE
)
1270 BOOL ret
= dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1271 if (ret
) free_xrender_picture( physdev
); /* pict format doesn't change, only drawable */
1275 return dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1278 /****************************************************************************
1279 * xrenderdrv_CopyBitmap
1281 static BOOL
xrenderdrv_CopyBitmap( HBITMAP src
, HBITMAP dst
)
1283 return X11DRV_CopyBitmap( src
, dst
);
1286 /****************************************************************************
1287 * xrenderdrv_CreateBitmap
1289 static BOOL
xrenderdrv_CreateBitmap( PHYSDEV dev
, HBITMAP hbitmap
)
1291 enum wxr_format format
;
1294 if (!GetObjectW( hbitmap
, sizeof(bitmap
), &bitmap
)) return FALSE
;
1296 if (bitmap
.bmPlanes
!= 1) return FALSE
;
1297 format
= get_bitmap_format( bitmap
.bmBitsPixel
);
1299 if (pict_formats
[format
])
1300 return X11DRV_create_phys_bitmap( hbitmap
, &bitmap
, pict_formats
[format
]->depth
,
1301 TRUE
, &wxr_color_shifts
[format
] );
1303 dev
= GET_NEXT_PHYSDEV( dev
, pCreateBitmap
);
1304 return dev
->funcs
->pCreateBitmap( dev
, hbitmap
);
1307 /****************************************************************************
1308 * xrenderdrv_DeleteBitmap
1310 static BOOL
xrenderdrv_DeleteBitmap( HBITMAP hbitmap
)
1312 return X11DRV_DeleteBitmap( hbitmap
);
1315 /***********************************************************************
1316 * xrenderdrv_SelectBitmap
1318 static HBITMAP
xrenderdrv_SelectBitmap( PHYSDEV dev
, HBITMAP hbitmap
)
1321 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1323 dev
= GET_NEXT_PHYSDEV( dev
, pSelectBitmap
);
1324 ret
= dev
->funcs
->pSelectBitmap( dev
, hbitmap
);
1327 free_xrender_picture( physdev
);
1328 physdev
->format
= get_xrender_format_from_color_shifts( physdev
->x11dev
->depth
,
1329 physdev
->x11dev
->color_shifts
);
1330 physdev
->pict_format
= pict_formats
[physdev
->format
];
1335 /***********************************************************************
1336 * xrenderdrv_GetImage
1338 static DWORD
xrenderdrv_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1339 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
1341 if (hbitmap
) return X11DRV_GetImage( dev
, hbitmap
, info
, bits
, src
);
1342 dev
= GET_NEXT_PHYSDEV( dev
, pGetImage
);
1343 return dev
->funcs
->pGetImage( dev
, hbitmap
, info
, bits
, src
);
1346 /***********************************************************************
1347 * xrenderdrv_SetDeviceClipping
1349 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev
, HRGN vis_rgn
, HRGN clip_rgn
)
1351 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1353 physdev
->update_clip
= TRUE
;
1355 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
1356 dev
->funcs
->pSetDeviceClipping( dev
, vis_rgn
, clip_rgn
);
1360 BOOL
X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP
*physBitmap
, int bits_pixel
, const DIBSECTION
*dib
)
1362 XRenderPictFormat
*pict_format
;
1364 const DWORD
*bitfields
;
1365 static const DWORD bitfields_32
[3] = {0xff0000, 0x00ff00, 0x0000ff};
1366 static const DWORD bitfields_16
[3] = {0x7c00, 0x03e0, 0x001f};
1369 /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1370 * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1371 * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1372 if (!X11DRV_XRender_Installed
|| bits_pixel
<= 8)
1375 if(dib
->dsBmih
.biCompression
== BI_BITFIELDS
)
1376 bitfields
= dib
->dsBitfields
;
1377 else if(bits_pixel
== 24 || bits_pixel
== 32)
1378 bitfields
= bitfields_32
;
1380 bitfields
= bitfields_16
;
1382 X11DRV_PALETTE_ComputeColorShifts(&shifts
, bitfields
[0], bitfields
[1], bitfields
[2]);
1383 pict_format
= pict_formats
[get_xrender_format_from_color_shifts(dib
->dsBm
.bmBitsPixel
, &shifts
)];
1385 /* Common formats should be in our picture format table. */
1388 TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1389 dib
->dsBm
.bmBitsPixel
, bitfields
[0], bitfields
[1], bitfields
[2]);
1393 physBitmap
->depth
= pict_format
->depth
;
1394 physBitmap
->trueColor
= TRUE
;
1395 physBitmap
->color_shifts
= shifts
;
1399 /************************************************************************
1402 * Helper to ExtTextOut. Must be called inside xrender_cs
1404 static void UploadGlyph(struct xrender_physdev
*physDev
, int glyph
, AA_Type format
)
1406 unsigned int buflen
;
1411 gsCacheEntry
*entry
= glyphsetCache
+ physDev
->cache_index
;
1412 gsCacheEntryFormat
*formatEntry
;
1413 UINT ggo_format
= GGO_GLYPH_INDEX
;
1414 enum wxr_format wxr_format
;
1415 static const char zero
[4];
1416 static const MAT2 identity
= { {0,1},{0,0},{0,0},{0,1} };
1420 ggo_format
|= WINE_GGO_GRAY16_BITMAP
;
1423 ggo_format
|= WINE_GGO_HRGB_BITMAP
;
1426 ggo_format
|= WINE_GGO_HBGR_BITMAP
;
1429 ggo_format
|= WINE_GGO_VRGB_BITMAP
;
1432 ggo_format
|= WINE_GGO_VBGR_BITMAP
;
1436 ERR("aa = %d - not implemented\n", format
);
1438 ggo_format
|= GGO_BITMAP
;
1442 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1443 if(buflen
== GDI_ERROR
) {
1444 if(format
!= AA_None
) {
1446 entry
->aa_default
= AA_None
;
1447 ggo_format
= GGO_GLYPH_INDEX
| GGO_BITMAP
;
1448 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1450 if(buflen
== GDI_ERROR
) {
1451 WARN("GetGlyphOutlineW failed using default glyph\n");
1452 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0, ggo_format
, &gm
, 0, NULL
, &identity
);
1453 if(buflen
== GDI_ERROR
) {
1454 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1455 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0x20, ggo_format
, &gm
, 0, NULL
, &identity
);
1456 if(buflen
== GDI_ERROR
) {
1457 ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1462 TRACE("Turning off antialiasing for this monochrome font\n");
1465 /* If there is nothing for the current type, we create the entry. */
1466 if( !entry
->format
[format
] ) {
1467 entry
->format
[format
] = HeapAlloc(GetProcessHeap(),
1469 sizeof(gsCacheEntryFormat
));
1471 formatEntry
= entry
->format
[format
];
1473 if(formatEntry
->nrealized
<= glyph
) {
1474 formatEntry
->nrealized
= (glyph
/ 128 + 1) * 128;
1476 if (formatEntry
->realized
)
1477 formatEntry
->realized
= HeapReAlloc(GetProcessHeap(),
1479 formatEntry
->realized
,
1480 formatEntry
->nrealized
* sizeof(BOOL
));
1482 formatEntry
->realized
= HeapAlloc(GetProcessHeap(),
1484 formatEntry
->nrealized
* sizeof(BOOL
));
1486 if(!X11DRV_XRender_Installed
) {
1487 if (formatEntry
->bitmaps
)
1488 formatEntry
->bitmaps
= HeapReAlloc(GetProcessHeap(),
1490 formatEntry
->bitmaps
,
1491 formatEntry
->nrealized
* sizeof(formatEntry
->bitmaps
[0]));
1493 formatEntry
->bitmaps
= HeapAlloc(GetProcessHeap(),
1495 formatEntry
->nrealized
* sizeof(formatEntry
->bitmaps
[0]));
1497 if (formatEntry
->gis
)
1498 formatEntry
->gis
= HeapReAlloc(GetProcessHeap(),
1501 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1503 formatEntry
->gis
= HeapAlloc(GetProcessHeap(),
1505 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1509 if(formatEntry
->glyphset
== 0 && X11DRV_XRender_Installed
) {
1512 wxr_format
= WXR_FORMAT_GRAY
;
1519 wxr_format
= WXR_FORMAT_A8R8G8B8
;
1523 ERR("aa = %d - not implemented\n", format
);
1525 wxr_format
= WXR_FORMAT_MONO
;
1530 formatEntry
->font_format
= pict_formats
[wxr_format
];
1531 formatEntry
->glyphset
= pXRenderCreateGlyphSet(gdi_display
, formatEntry
->font_format
);
1532 wine_tsx11_unlock();
1536 buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buflen
);
1537 GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, buflen
, buf
, &identity
);
1538 formatEntry
->realized
[glyph
] = TRUE
;
1540 TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1542 gm
.gmBlackBoxX
, gm
.gmBlackBoxY
, gm
.gmCellIncX
, gm
.gmCellIncY
,
1543 gm
.gmptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.y
);
1545 gi
.width
= gm
.gmBlackBoxX
;
1546 gi
.height
= gm
.gmBlackBoxY
;
1547 gi
.x
= -gm
.gmptGlyphOrigin
.x
;
1548 gi
.y
= gm
.gmptGlyphOrigin
.y
;
1549 gi
.xOff
= gm
.gmCellIncX
;
1550 gi
.yOff
= gm
.gmCellIncY
;
1552 if(TRACE_ON(xrender
)) {
1555 unsigned char *line
;
1557 if(format
== AA_None
) {
1558 pitch
= ((gi
.width
+ 31) / 32) * 4;
1559 for(i
= 0; i
< gi
.height
; i
++) {
1560 line
= (unsigned char*) buf
+ i
* pitch
;
1562 for(j
= 0; j
< pitch
* 8; j
++) {
1563 strcat(output
, (line
[j
/ 8] & (1 << (7 - (j
% 8)))) ? "#" : " ");
1565 TRACE("%s\n", output
);
1568 static const char blks
[] = " .:;!o*#";
1572 pitch
= ((gi
.width
+ 3) / 4) * 4;
1573 for(i
= 0; i
< gi
.height
; i
++) {
1574 line
= (unsigned char*) buf
+ i
* pitch
;
1576 for(j
= 0; j
< pitch
; j
++) {
1577 str
[0] = blks
[line
[j
] >> 5];
1578 strcat(output
, str
);
1580 TRACE("%s\n", output
);
1586 if(formatEntry
->glyphset
) {
1587 if(format
== AA_None
&& BitmapBitOrder(gdi_display
) != MSBFirst
) {
1588 unsigned char *byte
= (unsigned char*) buf
, c
;
1594 /* magic to flip bit order */
1595 c
= ((c
<< 1) & 0xaa) | ((c
>> 1) & 0x55);
1596 c
= ((c
<< 2) & 0xcc) | ((c
>> 2) & 0x33);
1597 c
= ((c
<< 4) & 0xf0) | ((c
>> 4) & 0x0f);
1602 else if ( format
!= AA_Grey
&&
1603 ImageByteOrder (gdi_display
) != NATIVE_BYTE_ORDER
)
1605 unsigned int i
, *data
= (unsigned int *)buf
;
1606 for (i
= buflen
/ sizeof(int); i
; i
--, data
++) *data
= RtlUlongByteSwap(*data
);
1611 XRenderCompositeText seems to ignore 0x0 glyphs when
1612 AA_None, which means we lose the advance width of glyphs
1613 like the space. We'll pretend that such glyphs are 1x1
1618 gi
.width
= gi
.height
= 1;
1621 pXRenderAddGlyphs(gdi_display
, formatEntry
->glyphset
, &gid
, &gi
, 1,
1622 buflen
? buf
: zero
, buflen
? buflen
: sizeof(zero
));
1623 wine_tsx11_unlock();
1624 HeapFree(GetProcessHeap(), 0, buf
);
1626 formatEntry
->bitmaps
[glyph
] = buf
;
1629 formatEntry
->gis
[glyph
] = gi
;
1632 static void SharpGlyphMono(struct xrender_physdev
*physDev
, INT x
, INT y
,
1633 void *bitmap
, XGlyphInfo
*gi
)
1635 unsigned char *srcLine
= bitmap
, *src
;
1636 unsigned char bits
, bitsMask
;
1637 int width
= gi
->width
;
1638 int stride
= ((width
+ 31) & ~31) >> 3;
1639 int height
= gi
->height
;
1643 TRACE("%d, %d\n", x
, y
);
1652 bitsMask
= 0x80; /* FreeType is always MSB first */
1658 if (bits
& bitsMask
)
1666 bitsMask
= bitsMask
>> 1;
1672 } while (bits
& bitsMask
);
1673 XFillRectangle (gdi_display
, physDev
->x11dev
->drawable
,
1674 physDev
->x11dev
->gc
, xspan
, y
, lenspan
, 1);
1686 bitsMask
= bitsMask
>> 1;
1692 } while (!(bits
& bitsMask
));
1699 static void SharpGlyphGray(struct xrender_physdev
*physDev
, INT x
, INT y
,
1700 void *bitmap
, XGlyphInfo
*gi
)
1702 unsigned char *srcLine
= bitmap
, *src
, bits
;
1703 int width
= gi
->width
;
1704 int stride
= ((width
+ 3) & ~3);
1705 int height
= gi
->height
;
1730 } while (bits
>= 0x80);
1731 XFillRectangle (gdi_display
, physDev
->x11dev
->drawable
,
1732 physDev
->x11dev
->gc
, xspan
, y
, lenspan
, 1);
1745 } while (bits
< 0x80);
1753 static void ExamineBitfield (DWORD mask
, int *shift
, int *len
)
1758 while ((mask
& 1) == 0)
1764 while ((mask
& 1) == 1)
1773 static DWORD
GetField (DWORD pixel
, int shift
, int len
)
1775 pixel
= pixel
& (((1 << (len
)) - 1) << shift
);
1776 pixel
= pixel
<< (32 - (shift
+ len
)) >> 24;
1779 pixel
|= (pixel
>> len
);
1786 static DWORD
PutField (DWORD pixel
, int shift
, int len
)
1788 shift
= shift
- (8 - len
);
1790 pixel
&= (((1 << len
) - 1) << (8 - len
));
1798 static void SmoothGlyphGray(XImage
*image
, int x
, int y
, void *bitmap
, XGlyphInfo
*gi
,
1804 BYTE
*maskLine
, *mask
, m
;
1809 BYTE src_r
, src_g
, src_b
;
1814 height
= gi
->height
;
1817 maskStride
= (width
+ 3) & ~3;
1819 ExamineBitfield (image
->red_mask
, &r_shift
, &r_len
);
1820 ExamineBitfield (image
->green_mask
, &g_shift
, &g_len
);
1821 ExamineBitfield (image
->blue_mask
, &b_shift
, &b_len
);
1823 src_r
= GetField(color
, r_shift
, r_len
);
1824 src_g
= GetField(color
, g_shift
, g_len
);
1825 src_b
= GetField(color
, b_shift
, b_len
);
1827 for(; height
--; y
++)
1830 maskLine
+= maskStride
;
1835 if(y
>= image
->height
) break;
1839 if(tx
>= image
->width
) break;
1842 if(tx
< 0) continue;
1845 XPutPixel (image
, tx
, y
, color
);
1850 pixel
= XGetPixel (image
, tx
, y
);
1852 r
= GetField(pixel
, r_shift
, r_len
);
1853 r
= ((BYTE
)~m
* (WORD
)r
+ (BYTE
)m
* (WORD
)src_r
) >> 8;
1854 g
= GetField(pixel
, g_shift
, g_len
);
1855 g
= ((BYTE
)~m
* (WORD
)g
+ (BYTE
)m
* (WORD
)src_g
) >> 8;
1856 b
= GetField(pixel
, b_shift
, b_len
);
1857 b
= ((BYTE
)~m
* (WORD
)b
+ (BYTE
)m
* (WORD
)src_b
) >> 8;
1859 pixel
= (PutField (r
, r_shift
, r_len
) |
1860 PutField (g
, g_shift
, g_len
) |
1861 PutField (b
, b_shift
, b_len
));
1862 XPutPixel (image
, tx
, y
, pixel
);
1868 /*************************************************************
1871 * Returns an appropriate Picture for tiling the text colour.
1872 * Call and use result within the xrender_cs
1874 static Picture
get_tile_pict( enum wxr_format wxr_format
, const XRenderColor
*color
)
1880 XRenderColor current_color
;
1881 } tiles
[WXR_NB_FORMATS
], *tile
;
1883 tile
= &tiles
[wxr_format
];
1887 XRenderPictureAttributes pa
;
1888 XRenderPictFormat
*pict_format
= pict_formats
[wxr_format
];
1891 tile
->xpm
= XCreatePixmap(gdi_display
, root_window
, 1, 1, pict_format
->depth
);
1893 pa
.repeat
= RepeatNormal
;
1894 tile
->pict
= pXRenderCreatePicture(gdi_display
, tile
->xpm
, pict_format
, CPRepeat
, &pa
);
1895 wine_tsx11_unlock();
1897 /* init current_color to something different from text_pixel */
1898 tile
->current_color
= *color
;
1899 tile
->current_color
.red
^= 0xffff;
1901 if (wxr_format
== WXR_FORMAT_MONO
)
1903 /* for a 1bpp bitmap we always need a 1 in the tile */
1905 col
.red
= col
.green
= col
.blue
= 0;
1908 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, &col
, 0, 0, 1, 1);
1909 wine_tsx11_unlock();
1913 if (memcmp( color
, &tile
->current_color
, sizeof(*color
) ) && wxr_format
!= WXR_FORMAT_MONO
)
1916 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, color
, 0, 0, 1, 1);
1917 wine_tsx11_unlock();
1918 tile
->current_color
= *color
;
1923 /*************************************************************
1926 * Returns an appropriate Picture for masking with the specified alpha.
1927 * Call and use result within the xrender_cs
1929 static Picture
get_mask_pict( int alpha
)
1931 static Pixmap pixmap
;
1932 static Picture pict
;
1933 static int current_alpha
;
1935 if (alpha
== 0xffff) return 0; /* don't need a mask for alpha==1.0 */
1939 XRenderPictureAttributes pa
;
1942 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
1943 pa
.repeat
= RepeatNormal
;
1944 pict
= pXRenderCreatePicture( gdi_display
, pixmap
,
1945 pict_formats
[WXR_FORMAT_A8R8G8B8
], CPRepeat
, &pa
);
1946 wine_tsx11_unlock();
1950 if (alpha
!= current_alpha
)
1953 col
.red
= col
.green
= col
.blue
= 0;
1954 col
.alpha
= current_alpha
= alpha
;
1956 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
1957 wine_tsx11_unlock();
1962 static int XRenderErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
1967 /***********************************************************************
1968 * xrenderdrv_ExtTextOut
1970 static BOOL
xrenderdrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
,
1971 const RECT
*lprect
, LPCWSTR wstr
, UINT count
, const INT
*lpDx
)
1973 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1975 gsCacheEntry
*entry
;
1976 gsCacheEntryFormat
*formatEntry
;
1978 int textPixel
, backgroundPixel
;
1979 RGNDATA
*saved_region
= NULL
;
1980 AA_Type aa_type
= AA_None
;
1982 Picture tile_pict
= 0;
1984 if (!physdev
->x11dev
->has_gdi_font
)
1986 dev
= GET_NEXT_PHYSDEV( dev
, pExtTextOut
);
1987 return dev
->funcs
->pExtTextOut( dev
, x
, y
, flags
, lprect
, wstr
, count
, lpDx
);
1990 xgcval
.function
= GXcopy
;
1991 xgcval
.background
= physdev
->x11dev
->backgroundPixel
;
1992 xgcval
.fill_style
= FillSolid
;
1994 XChangeGC( gdi_display
, physdev
->x11dev
->gc
, GCFunction
| GCBackground
| GCFillStyle
, &xgcval
);
1995 wine_tsx11_unlock();
1997 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
1999 if(physdev
->x11dev
->depth
== 1) {
2000 if((physdev
->x11dev
->textPixel
& 0xffffff) == 0) {
2002 backgroundPixel
= 1;
2005 backgroundPixel
= 0;
2008 textPixel
= physdev
->x11dev
->textPixel
;
2009 backgroundPixel
= physdev
->x11dev
->backgroundPixel
;
2012 if(flags
& ETO_OPAQUE
)
2015 XSetForeground( gdi_display
, physdev
->x11dev
->gc
, backgroundPixel
);
2016 XFillRectangle( gdi_display
, physdev
->x11dev
->drawable
, physdev
->x11dev
->gc
,
2017 physdev
->x11dev
->dc_rect
.left
+ lprect
->left
, physdev
->x11dev
->dc_rect
.top
+ lprect
->top
,
2018 lprect
->right
- lprect
->left
, lprect
->bottom
- lprect
->top
);
2019 wine_tsx11_unlock();
2028 EnterCriticalSection(&xrender_cs
);
2030 entry
= glyphsetCache
+ physdev
->cache_index
;
2031 aa_type
= entry
->aa_default
;
2032 formatEntry
= entry
->format
[aa_type
];
2034 for(idx
= 0; idx
< count
; idx
++) {
2035 if( !formatEntry
) {
2036 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
2037 /* re-evaluate antialias since aa_default may have changed */
2038 aa_type
= entry
->aa_default
;
2039 formatEntry
= entry
->format
[aa_type
];
2040 } else if( wstr
[idx
] >= formatEntry
->nrealized
|| formatEntry
->realized
[wstr
[idx
]] == FALSE
) {
2041 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
2046 WARN("could not upload requested glyphs\n");
2047 LeaveCriticalSection(&xrender_cs
);
2051 TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr
,count
),
2052 physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
2054 if(X11DRV_XRender_Installed
)
2056 XGlyphElt16
*elts
= HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16
) * count
);
2057 POINT offset
= {0, 0};
2058 POINT desired
, current
;
2059 int render_op
= PictOpOver
;
2060 Picture pict
= get_xrender_picture( physdev
, 0, (flags
& ETO_CLIPPED
) ? lprect
: NULL
);
2063 /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
2064 So we pass zeros to the function and move to our starting position using the first
2065 element of the elts array. */
2067 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
;
2068 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
;
2069 current
.x
= current
.y
= 0;
2071 get_xrender_color(physdev
->pict_format
, physdev
->x11dev
->textPixel
, &col
);
2072 tile_pict
= get_tile_pict(physdev
->format
, &col
);
2074 /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
2076 if((physdev
->format
== WXR_FORMAT_MONO
) && (textPixel
== 0))
2077 render_op
= PictOpOutReverse
; /* This gives us 'black' text */
2079 for(idx
= 0; idx
< count
; idx
++)
2081 elts
[idx
].glyphset
= formatEntry
->glyphset
;
2082 elts
[idx
].chars
= wstr
+ idx
;
2083 elts
[idx
].nchars
= 1;
2084 elts
[idx
].xOff
= desired
.x
- current
.x
;
2085 elts
[idx
].yOff
= desired
.y
- current
.y
;
2087 current
.x
+= (elts
[idx
].xOff
+ formatEntry
->gis
[wstr
[idx
]].xOff
);
2088 current
.y
+= (elts
[idx
].yOff
+ formatEntry
->gis
[wstr
[idx
]].yOff
);
2092 desired
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2093 desired
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2099 offset
.x
+= lpDx
[idx
* 2];
2100 offset
.y
+= lpDx
[idx
* 2 + 1];
2103 offset
.x
+= lpDx
[idx
];
2104 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
;
2105 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
;
2110 /* Make sure we don't have any transforms set from a previous call */
2111 set_xrender_transformation(pict
, 1, 1, 0, 0);
2112 pXRenderCompositeText16(gdi_display
, render_op
,
2115 formatEntry
->font_format
,
2116 0, 0, 0, 0, elts
, count
);
2117 wine_tsx11_unlock();
2118 HeapFree(GetProcessHeap(), 0, elts
);
2120 POINT offset
= {0, 0};
2122 if (flags
& ETO_CLIPPED
)
2124 HRGN clip_region
= CreateRectRgnIndirect( lprect
);
2125 saved_region
= add_extra_clipping_region( physdev
->x11dev
, clip_region
);
2126 DeleteObject( clip_region
);
2130 XSetForeground( gdi_display
, physdev
->x11dev
->gc
, textPixel
);
2132 if(aa_type
== AA_None
|| physdev
->x11dev
->depth
== 1)
2134 void (* sharp_glyph_fn
)(struct xrender_physdev
*, INT
, INT
, void *, XGlyphInfo
*);
2136 if(aa_type
== AA_None
)
2137 sharp_glyph_fn
= SharpGlyphMono
;
2139 sharp_glyph_fn
= SharpGlyphGray
;
2141 for(idx
= 0; idx
< count
; idx
++) {
2142 sharp_glyph_fn(physdev
,
2143 physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
,
2144 physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
,
2145 formatEntry
->bitmaps
[wstr
[idx
]],
2146 &formatEntry
->gis
[wstr
[idx
]]);
2151 offset
.x
+= lpDx
[idx
* 2];
2152 offset
.y
+= lpDx
[idx
* 2 + 1];
2155 offset
.x
+= lpDx
[idx
];
2159 offset
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2160 offset
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2165 int image_x
, image_y
, image_off_x
, image_off_y
, image_w
, image_h
;
2166 RECT extents
= {0, 0, 0, 0};
2168 int w
= physdev
->x11dev
->drawable_rect
.right
- physdev
->x11dev
->drawable_rect
.left
;
2169 int h
= physdev
->x11dev
->drawable_rect
.bottom
- physdev
->x11dev
->drawable_rect
.top
;
2171 TRACE("drawable %dx%d\n", w
, h
);
2173 for(idx
= 0; idx
< count
; idx
++) {
2174 if(extents
.left
> cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
)
2175 extents
.left
= cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
;
2176 if(extents
.top
> cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
)
2177 extents
.top
= cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
;
2178 if(extents
.right
< cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
+ formatEntry
->gis
[wstr
[idx
]].width
)
2179 extents
.right
= cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
+ formatEntry
->gis
[wstr
[idx
]].width
;
2180 if(extents
.bottom
< cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
+ formatEntry
->gis
[wstr
[idx
]].height
)
2181 extents
.bottom
= cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
+ formatEntry
->gis
[wstr
[idx
]].height
;
2187 cur
.x
+= lpDx
[idx
* 2];
2188 cur
.y
+= lpDx
[idx
* 2 + 1];
2195 cur
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2196 cur
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2199 TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents
.left
, extents
.top
,
2200 extents
.right
, extents
.bottom
, physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
2202 if(physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
>= 0) {
2203 image_x
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
;
2207 image_off_x
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
;
2209 if(physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
>= 0) {
2210 image_y
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
;
2214 image_off_y
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
;
2216 if(physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.right
< w
)
2217 image_w
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.right
- image_x
;
2219 image_w
= w
- image_x
;
2220 if(physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.bottom
< h
)
2221 image_h
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.bottom
- image_y
;
2223 image_h
= h
- image_y
;
2225 if(image_w
<= 0 || image_h
<= 0) goto no_image
;
2227 X11DRV_expect_error(gdi_display
, XRenderErrorHandler
, NULL
);
2228 image
= XGetImage(gdi_display
, physdev
->x11dev
->drawable
,
2229 image_x
, image_y
, image_w
, image_h
,
2230 AllPlanes
, ZPixmap
);
2231 X11DRV_check_error();
2233 TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2234 gdi_display
, (int)physdev
->x11dev
->drawable
, image_x
, image_y
,
2235 image_w
, image_h
, AllPlanes
, ZPixmap
,
2236 physdev
->x11dev
->depth
, image
);
2238 Pixmap xpm
= XCreatePixmap(gdi_display
, root_window
, image_w
, image_h
,
2239 physdev
->x11dev
->depth
);
2243 gcv
.graphics_exposures
= False
;
2244 gc
= XCreateGC(gdi_display
, xpm
, GCGraphicsExposures
, &gcv
);
2245 XCopyArea(gdi_display
, physdev
->x11dev
->drawable
, xpm
, gc
, image_x
, image_y
,
2246 image_w
, image_h
, 0, 0);
2247 XFreeGC(gdi_display
, gc
);
2248 X11DRV_expect_error(gdi_display
, XRenderErrorHandler
, NULL
);
2249 image
= XGetImage(gdi_display
, xpm
, 0, 0, image_w
, image_h
, AllPlanes
,
2251 X11DRV_check_error();
2252 XFreePixmap(gdi_display
, xpm
);
2254 if(!image
) goto no_image
;
2256 image
->red_mask
= visual
->red_mask
;
2257 image
->green_mask
= visual
->green_mask
;
2258 image
->blue_mask
= visual
->blue_mask
;
2260 for(idx
= 0; idx
< count
; idx
++) {
2261 SmoothGlyphGray(image
,
2262 offset
.x
+ image_off_x
- extents
.left
,
2263 offset
.y
+ image_off_y
- extents
.top
,
2264 formatEntry
->bitmaps
[wstr
[idx
]],
2265 &formatEntry
->gis
[wstr
[idx
]],
2266 physdev
->x11dev
->textPixel
);
2271 offset
.x
+= lpDx
[idx
* 2];
2272 offset
.y
+= lpDx
[idx
* 2 + 1];
2275 offset
.x
+= lpDx
[idx
];
2279 offset
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2280 offset
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2283 XPutImage(gdi_display
, physdev
->x11dev
->drawable
, physdev
->x11dev
->gc
, image
, 0, 0,
2284 image_x
, image_y
, image_w
, image_h
);
2285 XDestroyImage(image
);
2288 wine_tsx11_unlock();
2289 restore_clipping_region( physdev
->x11dev
, saved_region
);
2291 LeaveCriticalSection(&xrender_cs
);
2295 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2299 /* multiply the alpha channel of a picture */
2300 static void multiply_alpha( Picture pict
, XRenderPictFormat
*format
, int alpha
,
2301 int x
, int y
, int width
, int height
)
2303 XRenderPictureAttributes pa
;
2304 Pixmap src_pixmap
, mask_pixmap
;
2305 Picture src_pict
, mask_pict
;
2309 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
2310 mask_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
2311 pa
.repeat
= RepeatNormal
;
2312 src_pict
= pXRenderCreatePicture( gdi_display
, src_pixmap
, format
, CPRepeat
, &pa
);
2313 pa
.component_alpha
= True
;
2314 mask_pict
= pXRenderCreatePicture( gdi_display
, mask_pixmap
, format
, CPRepeat
|CPComponentAlpha
, &pa
);
2315 color
.red
= color
.green
= color
.blue
= color
.alpha
= 0xffff;
2316 pXRenderFillRectangle( gdi_display
, PictOpSrc
, src_pict
, &color
, 0, 0, 1, 1 );
2317 color
.alpha
= alpha
;
2318 pXRenderFillRectangle( gdi_display
, PictOpSrc
, mask_pict
, &color
, 0, 0, 1, 1 );
2319 pXRenderComposite( gdi_display
, PictOpInReverse
, src_pict
, mask_pict
, pict
,
2320 0, 0, 0, 0, x
, y
, width
, height
);
2321 pXRenderFreePicture( gdi_display
, src_pict
);
2322 pXRenderFreePicture( gdi_display
, mask_pict
);
2323 XFreePixmap( gdi_display
, src_pixmap
);
2324 XFreePixmap( gdi_display
, mask_pixmap
);
2325 wine_tsx11_unlock();
2328 /* Helper function for (stretched) blitting using xrender */
2329 static void xrender_blit( int op
, Picture src_pict
, Picture mask_pict
, Picture dst_pict
,
2330 int x_src
, int y_src
, int x_dst
, int y_dst
,
2331 double xscale
, double yscale
, int width
, int height
)
2333 int x_offset
, y_offset
;
2335 /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2336 * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2337 * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2339 if(xscale
!= 1.0 || yscale
!= 1.0)
2341 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2342 * in the wrong quadrant of the x-y plane.
2344 x_offset
= (xscale
< 0) ? -width
: 0;
2345 y_offset
= (yscale
< 0) ? -height
: 0;
2346 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
2352 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
2354 pXRenderComposite( gdi_display
, op
, src_pict
, mask_pict
, dst_pict
,
2355 x_offset
, y_offset
, 0, 0, x_dst
, y_dst
, width
, height
);
2356 wine_tsx11_unlock();
2359 /* Helper function for (stretched) mono->color blitting using xrender */
2360 static void xrender_mono_blit( Picture src_pict
, Picture dst_pict
,
2361 enum wxr_format dst_format
, XRenderColor
*fg
, XRenderColor
*bg
,
2362 int x_src
, int y_src
, int x_dst
, int y_dst
,
2363 double xscale
, double yscale
, int width
, int height
)
2366 int x_offset
, y_offset
;
2369 /* When doing a mono->color blit, the source data is used as mask, and the source picture
2370 * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
2373 EnterCriticalSection( &xrender_cs
);
2375 color
.alpha
= 0xffff; /* tile pict needs 100% alpha */
2376 tile_pict
= get_tile_pict( dst_format
, &color
);
2379 pXRenderFillRectangle( gdi_display
, PictOpSrc
, dst_pict
, fg
, x_dst
, y_dst
, width
, height
);
2381 if (xscale
!= 1.0 || yscale
!= 1.0)
2383 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2384 * in the wrong quadrant of the x-y plane.
2386 x_offset
= (xscale
< 0) ? -width
: 0;
2387 y_offset
= (yscale
< 0) ? -height
: 0;
2388 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
2394 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
2396 pXRenderComposite(gdi_display
, PictOpOver
, tile_pict
, src_pict
, dst_pict
,
2397 0, 0, x_offset
, y_offset
, x_dst
, y_dst
, width
, height
);
2398 wine_tsx11_unlock();
2399 LeaveCriticalSection( &xrender_cs
);
2401 /* force the alpha channel for background pixels, it has been set to 100% by the tile */
2402 if (bg
->alpha
!= 0xffff && (dst_format
== WXR_FORMAT_A8R8G8B8
|| dst_format
== WXR_FORMAT_B8G8R8A8
))
2403 multiply_alpha( dst_pict
, pict_formats
[dst_format
], bg
->alpha
, x_dst
, y_dst
, width
, height
);
2406 /* create a pixmap and render picture for an image */
2407 static DWORD
create_image_pixmap( BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2408 struct bitblt_coords
*src
, enum wxr_format format
,
2409 Pixmap
*pixmap
, Picture
*pict
, BOOL
*use_repeat
)
2412 int width
= src
->visrect
.right
- src
->visrect
.left
;
2413 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2414 int depth
= pict_formats
[format
]->depth
;
2415 struct gdi_image_bits dst_bits
;
2416 XRenderPictureAttributes pa
;
2420 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
2421 info
->bmiHeader
.biWidth
, height
, 32, 0 );
2422 wine_tsx11_unlock();
2423 if (!image
) return ERROR_OUTOFMEMORY
;
2425 ret
= copy_image_bits( info
, (format
== WXR_FORMAT_R8G8B8
), image
, bits
, &dst_bits
, src
, NULL
, ~0u );
2426 if (ret
) return ret
;
2428 image
->data
= dst_bits
.ptr
;
2429 /* hack: make sure the bits are readable if we are reading from a DIB section */
2430 /* to be removed once we get rid of DIB access protections */
2431 if (!dst_bits
.is_copy
) IsBadReadPtr( dst_bits
.ptr
, image
->height
* image
->bytes_per_line
);
2433 *use_repeat
= (width
== 1 && height
== 1);
2434 pa
.repeat
= *use_repeat
? RepeatNormal
: RepeatNone
;
2437 *pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
2438 XPutImage( gdi_display
, *pixmap
, get_bitmap_gc( depth
), image
,
2439 src
->visrect
.left
, 0, 0, 0, width
, height
);
2440 *pict
= pXRenderCreatePicture( gdi_display
, *pixmap
, pict_formats
[format
], CPRepeat
, &pa
);
2441 wine_tsx11_unlock();
2443 /* make coordinates relative to the pixmap */
2444 src
->x
-= src
->visrect
.left
;
2445 src
->y
-= src
->visrect
.top
;
2446 OffsetRect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
2450 XDestroyImage( image
);
2451 wine_tsx11_unlock();
2452 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
2456 static void xrender_stretch_blit( struct xrender_physdev
*physdev_src
, struct xrender_physdev
*physdev_dst
,
2457 Drawable drawable
, const struct bitblt_coords
*src
,
2458 const struct bitblt_coords
*dst
)
2460 int width
= abs( dst
->width
);
2461 int height
= abs( dst
->height
);
2462 int x_src
= physdev_src
->x11dev
->dc_rect
.left
+ src
->x
;
2463 int y_src
= physdev_src
->x11dev
->dc_rect
.top
+ src
->y
;
2465 Picture src_pict
= 0, dst_pict
, mask_pict
= 0;
2467 double xscale
, yscale
;
2469 use_repeat
= use_source_repeat( physdev_src
);
2472 xscale
= src
->width
/ (double)dst
->width
;
2473 yscale
= src
->height
/ (double)dst
->height
;
2475 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2477 if (drawable
) /* using an intermediate pixmap */
2479 XRenderPictureAttributes pa
;
2483 pa
.repeat
= RepeatNone
;
2485 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, physdev_dst
->pict_format
, CPRepeat
, &pa
);
2486 wine_tsx11_unlock();
2490 x_dst
= physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
;
2491 y_dst
= physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
;
2492 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2495 if (src
->width
< 0) x_src
+= src
->width
+ 1;
2496 if (src
->height
< 0) y_src
+= src
->height
+ 1;
2497 if (dst
->width
< 0) x_dst
+= dst
->width
+ 1;
2498 if (dst
->height
< 0) y_dst
+= dst
->height
+ 1;
2500 src_pict
= get_xrender_picture_source( physdev_src
, use_repeat
);
2503 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2505 XRenderColor fg
, bg
;
2507 get_xrender_color( physdev_dst
->pict_format
, physdev_dst
->x11dev
->textPixel
, &fg
);
2508 get_xrender_color( physdev_dst
->pict_format
, physdev_dst
->x11dev
->backgroundPixel
, &bg
);
2509 fg
.alpha
= bg
.alpha
= 0;
2511 xrender_mono_blit( src_pict
, dst_pict
, physdev_dst
->format
, &fg
, &bg
,
2512 x_src
, y_src
, x_dst
, y_dst
, xscale
, yscale
, width
, height
);
2514 else /* color -> color (can be at different depths) or mono -> mono */
2516 if (physdev_dst
->x11dev
->depth
== 32 && physdev_src
->x11dev
->depth
< 32)
2517 mask_pict
= get_no_alpha_mask();
2519 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
,
2520 x_src
, y_src
, x_dst
, y_dst
, xscale
, yscale
, width
, height
);
2526 pXRenderFreePicture( gdi_display
, dst_pict
);
2527 wine_tsx11_unlock();
2532 static void xrender_put_image( Pixmap src_pixmap
, Picture src_pict
, Picture mask_pict
, HRGN clip
,
2533 XRenderPictFormat
*dst_format
, struct xrender_physdev
*physdev
,
2534 Drawable drawable
, struct bitblt_coords
*src
,
2535 struct bitblt_coords
*dst
, BOOL use_repeat
)
2537 int x_src
, y_src
, x_dst
, y_dst
;
2539 XRenderPictureAttributes pa
;
2540 double xscale
, yscale
;
2542 if (drawable
) /* using an intermediate pixmap */
2544 RGNDATA
*clip_data
= NULL
;
2546 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
2549 pa
.repeat
= RepeatNone
;
2551 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, dst_format
, CPRepeat
, &pa
);
2553 pXRenderSetPictureClipRectangles( gdi_display
, dst_pict
, 0, 0,
2554 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
2555 wine_tsx11_unlock();
2556 HeapFree( GetProcessHeap(), 0, clip_data
);
2560 x_dst
= physdev
->x11dev
->dc_rect
.left
+ dst
->x
;
2561 y_dst
= physdev
->x11dev
->dc_rect
.top
+ dst
->y
;
2562 dst_pict
= get_xrender_picture( physdev
, clip
, &dst
->visrect
);
2567 xscale
= src
->width
/ (double)dst
->width
;
2568 yscale
= src
->height
/ (double)dst
->height
;
2570 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2574 if (src
->width
< 0) x_src
+= src
->width
+ 1;
2575 if (src
->height
< 0) y_src
+= src
->height
+ 1;
2576 if (dst
->width
< 0) x_dst
+= dst
->width
+ 1;
2577 if (dst
->height
< 0) y_dst
+= dst
->height
+ 1;
2579 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
, x_src
, y_src
, x_dst
, y_dst
,
2580 xscale
, yscale
, abs( dst
->width
), abs( dst
->height
));
2585 pXRenderFreePicture( gdi_display
, dst_pict
);
2586 wine_tsx11_unlock();
2591 /***********************************************************************
2592 * xrenderdrv_StretchBlt
2594 static BOOL
xrenderdrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2595 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
2597 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2598 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2599 BOOL stretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
2601 if (src_dev
->funcs
!= dst_dev
->funcs
)
2603 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
2604 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
2607 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2609 /* XRender is of no use for color -> mono */
2610 if (physdev_dst
->format
== WXR_FORMAT_MONO
&& physdev_src
->format
!= WXR_FORMAT_MONO
)
2611 goto x11drv_fallback
;
2613 /* if not stretching, we only need to handle format conversion */
2614 if (!stretch
&& physdev_dst
->format
== physdev_src
->format
) goto x11drv_fallback
;
2616 X11DRV_LockDIBSection( physdev_dst
->x11dev
, DIB_Status_GdiMod
);
2617 if (physdev_dst
!= physdev_src
) X11DRV_LockDIBSection( physdev_src
->x11dev
, DIB_Status_GdiMod
);
2623 struct bitblt_coords tmp
;
2625 /* make coordinates relative to tmp pixmap */
2627 tmp
.x
-= tmp
.visrect
.left
;
2628 tmp
.y
-= tmp
.visrect
.top
;
2629 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2632 tmpGC
= XCreateGC( gdi_display
, physdev_dst
->x11dev
->drawable
, 0, NULL
);
2633 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
2634 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
2635 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2636 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev_dst
->x11dev
->depth
);
2637 wine_tsx11_unlock();
2639 xrender_stretch_blit( physdev_src
, physdev_dst
, tmp_pixmap
, src
, &tmp
);
2640 execute_rop( physdev_dst
->x11dev
, tmp_pixmap
, tmpGC
, &dst
->visrect
, rop
);
2643 XFreePixmap( gdi_display
, tmp_pixmap
);
2644 XFreeGC( gdi_display
, tmpGC
);
2645 wine_tsx11_unlock();
2647 else xrender_stretch_blit( physdev_src
, physdev_dst
, 0, src
, dst
);
2649 if (physdev_dst
!= physdev_src
) X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2650 X11DRV_UnlockDIBSection( physdev_dst
->x11dev
, TRUE
);
2654 return X11DRV_StretchBlt( &physdev_dst
->x11dev
->dev
, dst
, &physdev_src
->x11dev
->dev
, src
, rop
);
2658 /***********************************************************************
2659 * xrenderdrv_PutImage
2661 static DWORD
xrenderdrv_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
2662 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
2663 struct bitblt_coords
*dst
, DWORD rop
)
2665 struct xrender_physdev
*physdev
;
2666 X_PHYSBITMAP
*bitmap
;
2670 enum wxr_format src_format
, dst_format
;
2671 XRenderPictFormat
*pict_format
;
2673 Picture src_pict
, mask_pict
= 0;
2676 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2680 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
2682 dst_format
= get_xrender_format_from_color_shifts( bitmap
->depth
, &bitmap
->color_shifts
);
2686 physdev
= get_xrender_dev( dev
);
2688 dst_format
= physdev
->format
;
2691 src_format
= get_xrender_format_from_bitmapinfo( info
);
2692 if (!(pict_format
= pict_formats
[src_format
])) goto update_format
;
2694 /* make sure we can create an image with the same bpp */
2695 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2698 /* mono <-> color conversions not supported */
2699 if ((src_format
!= dst_format
) && (src_format
== WXR_FORMAT_MONO
|| dst_format
== WXR_FORMAT_MONO
))
2700 goto x11drv_fallback
;
2702 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2704 if (!has_alpha( src_format
) && has_alpha( dst_format
)) mask_pict
= get_no_alpha_mask();
2706 ret
= create_image_pixmap( info
, bits
, src
, src_format
, &src_pixmap
, &src_pict
, &use_repeat
);
2709 struct bitblt_coords tmp
;
2713 HRGN rgn
= CreateRectRgnIndirect( &dst
->visrect
);
2714 if (clip
) CombineRgn( rgn
, rgn
, clip
, RGN_AND
);
2716 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
2718 xrender_put_image( src_pixmap
, src_pict
, mask_pict
, rgn
,
2719 pict_formats
[dst_format
], NULL
, bitmap
->pixmap
, src
, dst
, use_repeat
);
2721 X11DRV_DIB_Unlock( bitmap
, TRUE
);
2722 DeleteObject( rgn
);
2726 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
2730 RGNDATA
*clip_data
= NULL
;
2732 /* make coordinates relative to tmp pixmap */
2734 tmp
.x
-= tmp
.visrect
.left
;
2735 tmp
.y
-= tmp
.visrect
.top
;
2736 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2738 if (clip
) clip_data
= add_extra_clipping_region( physdev
->x11dev
, clip
);
2741 gc
= XCreateGC( gdi_display
, physdev
->x11dev
->drawable
, 0, NULL
);
2742 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
2743 XSetGraphicsExposures( gdi_display
, gc
, False
);
2744 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2745 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev
->x11dev
->depth
);
2746 wine_tsx11_unlock();
2748 xrender_put_image( src_pixmap
, src_pict
, mask_pict
, NULL
, physdev
->pict_format
,
2749 NULL
, tmp_pixmap
, src
, &tmp
, use_repeat
);
2750 execute_rop( physdev
->x11dev
, tmp_pixmap
, gc
, &dst
->visrect
, rop
);
2753 XFreePixmap( gdi_display
, tmp_pixmap
);
2754 XFreeGC( gdi_display
, gc
);
2755 wine_tsx11_unlock();
2757 restore_clipping_region( physdev
->x11dev
, clip_data
);
2759 else xrender_put_image( src_pixmap
, src_pict
, mask_pict
, clip
,
2760 physdev
->pict_format
, physdev
, 0, src
, dst
, use_repeat
);
2762 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2766 pXRenderFreePicture( gdi_display
, src_pict
);
2767 XFreePixmap( gdi_display
, src_pixmap
);
2768 wine_tsx11_unlock();
2773 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2774 set_color_info( pict_formats
[dst_format
], info
);
2775 return ERROR_BAD_FORMAT
;
2778 if (hbitmap
) return X11DRV_PutImage( dev
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
2779 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
2780 return dev
->funcs
->pPutImage( dev
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
2784 /***********************************************************************
2785 * xrenderdrv_BlendImage
2787 static DWORD
xrenderdrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2788 struct bitblt_coords
*src
, struct bitblt_coords
*dst
,
2789 BLENDFUNCTION func
)
2791 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2793 enum wxr_format format
;
2794 XRenderPictFormat
*pict_format
;
2795 Picture dst_pict
, src_pict
, mask_pict
;
2799 if (!X11DRV_XRender_Installed
)
2801 dev
= GET_NEXT_PHYSDEV( dev
, pBlendImage
);
2802 return dev
->funcs
->pBlendImage( dev
, info
, bits
, src
, dst
, func
);
2805 format
= get_xrender_format_from_bitmapinfo( info
);
2806 if (!(func
.AlphaFormat
& AC_SRC_ALPHA
))
2807 format
= get_format_without_alpha( format
);
2808 else if (format
!= WXR_FORMAT_A8R8G8B8
)
2809 return ERROR_INVALID_PARAMETER
;
2811 if (!(pict_format
= pict_formats
[format
])) goto update_format
;
2813 /* make sure we can create an image with the same bpp */
2814 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2817 if (format
== WXR_FORMAT_MONO
&& physdev
->format
!= WXR_FORMAT_MONO
)
2820 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2822 ret
= create_image_pixmap( info
, bits
, src
, format
, &src_pixmap
, &src_pict
, &use_repeat
);
2825 double xscale
, yscale
;
2827 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
2831 xscale
= src
->width
/ (double)dst
->width
;
2832 yscale
= src
->height
/ (double)dst
->height
;
2834 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2836 dst_pict
= get_xrender_picture( physdev
, 0, &dst
->visrect
);
2838 EnterCriticalSection( &xrender_cs
);
2839 mask_pict
= get_mask_pict( func
.SourceConstantAlpha
* 257 );
2841 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
, src
->x
, src
->y
,
2842 physdev
->x11dev
->dc_rect
.left
+ dst
->x
,
2843 physdev
->x11dev
->dc_rect
.top
+ dst
->y
,
2844 xscale
, yscale
, dst
->width
, dst
->height
);
2847 pXRenderFreePicture( gdi_display
, src_pict
);
2848 XFreePixmap( gdi_display
, src_pixmap
);
2849 wine_tsx11_unlock();
2851 LeaveCriticalSection( &xrender_cs
);
2853 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2858 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2859 set_color_info( physdev
->pict_format
, info
);
2860 return ERROR_BAD_FORMAT
;
2864 /***********************************************************************
2865 * xrenderdrv_AlphaBlend
2867 static BOOL
xrenderdrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2868 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION blendfn
)
2870 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2871 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2872 Picture dst_pict
, src_pict
= 0, mask_pict
= 0, tmp_pict
= 0;
2873 XRenderPictureAttributes pa
;
2874 Pixmap tmp_pixmap
= 0;
2875 double xscale
, yscale
;
2878 if (!X11DRV_XRender_Installed
|| src_dev
->funcs
!= dst_dev
->funcs
)
2880 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
2881 return dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, blendfn
);
2884 if ((blendfn
.AlphaFormat
& AC_SRC_ALPHA
) && physdev_src
->format
!= WXR_FORMAT_A8R8G8B8
)
2886 SetLastError( ERROR_INVALID_PARAMETER
);
2890 X11DRV_LockDIBSection( physdev_dst
->x11dev
, DIB_Status_GdiMod
);
2891 if (physdev_dst
!= physdev_src
) X11DRV_LockDIBSection( physdev_src
->x11dev
, DIB_Status_GdiMod
);
2893 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2895 use_repeat
= use_source_repeat( physdev_src
);
2898 xscale
= src
->width
/ (double)dst
->width
;
2899 yscale
= src
->height
/ (double)dst
->height
;
2901 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2903 src_pict
= get_xrender_picture_source( physdev_src
, use_repeat
);
2905 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2907 /* mono -> color blending needs an intermediate color pixmap */
2908 XRenderColor fg
, bg
;
2909 int width
= src
->visrect
.right
- src
->visrect
.left
;
2910 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2912 /* blending doesn't use the destination DC colors */
2913 fg
.red
= fg
.green
= fg
.blue
= 0;
2914 bg
.red
= bg
.green
= bg
.blue
= 0xffff;
2915 fg
.alpha
= bg
.alpha
= 0xffff;
2918 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
,
2919 physdev_dst
->pict_format
->depth
);
2920 pa
.repeat
= use_repeat
? RepeatNormal
: RepeatNone
;
2921 tmp_pict
= pXRenderCreatePicture( gdi_display
, tmp_pixmap
, physdev_dst
->pict_format
,
2923 wine_tsx11_unlock();
2925 xrender_mono_blit( src_pict
, tmp_pict
, physdev_dst
->format
, &fg
, &bg
,
2926 src
->visrect
.left
, src
->visrect
.top
, 0, 0, 1, 1, width
, height
);
2928 else if (!(blendfn
.AlphaFormat
& AC_SRC_ALPHA
) && physdev_src
->pict_format
)
2930 /* we need a source picture with no alpha */
2931 enum wxr_format format
= get_format_without_alpha( physdev_src
->format
);
2932 if (format
!= physdev_src
->format
)
2935 pa
.subwindow_mode
= IncludeInferiors
;
2936 pa
.repeat
= use_repeat
? RepeatNormal
: RepeatNone
;
2937 tmp_pict
= pXRenderCreatePicture( gdi_display
, physdev_src
->x11dev
->drawable
,
2938 pict_formats
[format
], CPSubwindowMode
|CPRepeat
, &pa
);
2939 wine_tsx11_unlock();
2943 if (tmp_pict
) src_pict
= tmp_pict
;
2945 EnterCriticalSection( &xrender_cs
);
2946 mask_pict
= get_mask_pict( blendfn
.SourceConstantAlpha
* 257 );
2948 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
,
2949 physdev_src
->x11dev
->dc_rect
.left
+ src
->x
,
2950 physdev_src
->x11dev
->dc_rect
.top
+ src
->y
,
2951 physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
,
2952 physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
,
2953 xscale
, yscale
, dst
->width
, dst
->height
);
2956 if (tmp_pict
) pXRenderFreePicture( gdi_display
, tmp_pict
);
2957 if (tmp_pixmap
) XFreePixmap( gdi_display
, tmp_pixmap
);
2958 wine_tsx11_unlock();
2960 LeaveCriticalSection( &xrender_cs
);
2961 if (physdev_src
!= physdev_dst
) X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2962 X11DRV_UnlockDIBSection( physdev_dst
->x11dev
, TRUE
);
2966 /***********************************************************************
2967 * xrenderdrv_SelectBrush
2969 static HBRUSH
xrenderdrv_SelectBrush( PHYSDEV dev
, HBRUSH hbrush
, HBITMAP bitmap
,
2970 const BITMAPINFO
*info
, void *bits
, UINT usage
)
2972 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2973 X_PHYSBITMAP
*physbitmap
;
2974 enum wxr_format format
;
2975 BOOL delete_bitmap
= FALSE
;
2978 Picture src_pict
, dst_pict
;
2979 XRenderPictureAttributes pa
;
2981 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2982 if (!bitmap
&& !info
) goto x11drv_fallback
;
2983 if (physdev
->format
== WXR_FORMAT_MONO
) goto x11drv_fallback
;
2985 if (!bitmap
|| !(physbitmap
= X11DRV_get_phys_bitmap( bitmap
)))
2987 format
= get_bitmap_format( info
->bmiHeader
.biBitCount
);
2988 if (format
== physdev
->format
|| !pict_formats
[format
]) goto x11drv_fallback
;
2989 if (!(bitmap
= create_brush_bitmap( physdev
->x11dev
, info
, bits
, usage
))) return 0;
2990 physbitmap
= X11DRV_get_phys_bitmap( bitmap
);
2991 delete_bitmap
= TRUE
;
2995 format
= get_xrender_format_from_color_shifts( physbitmap
->depth
, &physbitmap
->color_shifts
);
2996 if (format
== WXR_FORMAT_MONO
|| format
== physdev
->format
|| !pict_formats
[format
])
2997 goto x11drv_fallback
;
3000 GetObjectW( bitmap
, sizeof(bm
), &bm
);
3002 X11DRV_DIB_Lock( physbitmap
, DIB_Status_GdiMod
);
3005 pixmap
= XCreatePixmap( gdi_display
, root_window
, bm
.bmWidth
, bm
.bmHeight
,
3006 physdev
->pict_format
->depth
);
3008 pa
.repeat
= RepeatNone
;
3009 src_pict
= pXRenderCreatePicture(gdi_display
, physbitmap
->pixmap
, pict_formats
[format
], CPRepeat
, &pa
);
3010 dst_pict
= pXRenderCreatePicture(gdi_display
, pixmap
, physdev
->pict_format
, CPRepeat
, &pa
);
3012 xrender_blit( PictOpSrc
, src_pict
, 0, dst_pict
, 0, 0, 0, 0, 1.0, 1.0, bm
.bmWidth
, bm
.bmHeight
);
3013 pXRenderFreePicture( gdi_display
, src_pict
);
3014 pXRenderFreePicture( gdi_display
, dst_pict
);
3016 if (physdev
->x11dev
->brush
.pixmap
) XFreePixmap( gdi_display
, physdev
->x11dev
->brush
.pixmap
);
3017 physdev
->x11dev
->brush
.pixmap
= pixmap
;
3018 physdev
->x11dev
->brush
.fillStyle
= FillTiled
;
3019 physdev
->x11dev
->brush
.pixel
= 0; /* ignored */
3020 wine_tsx11_unlock();
3022 X11DRV_DIB_Unlock( physbitmap
, TRUE
);
3023 if (delete_bitmap
) DeleteObject( bitmap
);
3027 if (delete_bitmap
) DeleteObject( bitmap
);
3028 dev
= GET_NEXT_PHYSDEV( dev
, pSelectBrush
);
3029 return dev
->funcs
->pSelectBrush( dev
, hbrush
, bitmap
, info
, bits
, usage
);
3033 static const struct gdi_dc_funcs xrender_funcs
=
3035 NULL
, /* pAbortDoc */
3036 NULL
, /* pAbortPath */
3037 xrenderdrv_AlphaBlend
, /* pAlphaBlend */
3038 NULL
, /* pAngleArc */
3041 NULL
, /* pBeginPath */
3042 xrenderdrv_BlendImage
, /* pBlendImage */
3043 NULL
, /* pChoosePixelFormat */
3045 NULL
, /* pCloseFigure */
3046 xrenderdrv_CopyBitmap
, /* pCopyBitmap */
3047 xrenderdrv_CreateBitmap
, /* pCreateBitmap */
3048 xrenderdrv_CreateCompatibleDC
, /* pCreateCompatibleDC */
3049 xrenderdrv_CreateDC
, /* pCreateDC */
3050 NULL
, /* pCreateDIBSection */
3051 xrenderdrv_DeleteBitmap
, /* pDeleteBitmap */
3052 xrenderdrv_DeleteDC
, /* pDeleteDC */
3053 NULL
, /* pDeleteObject */
3054 NULL
, /* pDescribePixelFormat */
3055 NULL
, /* pDeviceCapabilities */
3056 NULL
, /* pEllipse */
3058 NULL
, /* pEndPage */
3059 NULL
, /* pEndPath */
3060 NULL
, /* pEnumFonts */
3061 NULL
, /* pEnumICMProfiles */
3062 NULL
, /* pExcludeClipRect */
3063 NULL
, /* pExtDeviceMode */
3064 xrenderdrv_ExtEscape
, /* pExtEscape */
3065 NULL
, /* pExtFloodFill */
3066 NULL
, /* pExtSelectClipRgn */
3067 xrenderdrv_ExtTextOut
, /* pExtTextOut */
3068 NULL
, /* pFillPath */
3069 NULL
, /* pFillRgn */
3070 NULL
, /* pFlattenPath */
3071 NULL
, /* pFontIsLinked */
3072 NULL
, /* pFrameRgn */
3073 NULL
, /* pGdiComment */
3074 NULL
, /* pGdiRealizationInfo */
3075 NULL
, /* pGetCharABCWidths */
3076 NULL
, /* pGetCharABCWidthsI */
3077 NULL
, /* pGetCharWidth */
3078 NULL
, /* pGetDeviceCaps */
3079 NULL
, /* pGetDeviceGammaRamp */
3080 NULL
, /* pGetFontData */
3081 NULL
, /* pGetFontUnicodeRanges */
3082 NULL
, /* pGetGlyphIndices */
3083 NULL
, /* pGetGlyphOutline */
3084 NULL
, /* pGetICMProfile */
3085 xrenderdrv_GetImage
, /* pGetImage */
3086 NULL
, /* pGetKerningPairs */
3087 NULL
, /* pGetNearestColor */
3088 NULL
, /* pGetOutlineTextMetrics */
3089 NULL
, /* pGetPixel */
3090 NULL
, /* pGetPixelFormat */
3091 NULL
, /* pGetSystemPaletteEntries */
3092 NULL
, /* pGetTextCharsetInfo */
3093 NULL
, /* pGetTextExtentExPoint */
3094 NULL
, /* pGetTextExtentExPointI */
3095 NULL
, /* pGetTextFace */
3096 NULL
, /* pGetTextMetrics */
3097 NULL
, /* pGradientFill */
3098 NULL
, /* pIntersectClipRect */
3099 NULL
, /* pInvertRgn */
3101 NULL
, /* pModifyWorldTransform */
3103 NULL
, /* pOffsetClipRgn */
3104 NULL
, /* pOffsetViewportOrg */
3105 NULL
, /* pOffsetWindowOrg */
3106 NULL
, /* pPaintRgn */
3109 NULL
, /* pPolyBezier */
3110 NULL
, /* pPolyBezierTo */
3111 NULL
, /* pPolyDraw */
3112 NULL
, /* pPolyPolygon */
3113 NULL
, /* pPolyPolyline */
3114 NULL
, /* pPolygon */
3115 NULL
, /* pPolyline */
3116 NULL
, /* pPolylineTo */
3117 xrenderdrv_PutImage
, /* pPutImage */
3118 NULL
, /* pRealizeDefaultPalette */
3119 NULL
, /* pRealizePalette */
3120 NULL
, /* pRectangle */
3121 NULL
, /* pResetDC */
3122 NULL
, /* pRestoreDC */
3123 NULL
, /* pRoundRect */
3125 NULL
, /* pScaleViewportExt */
3126 NULL
, /* pScaleWindowExt */
3127 xrenderdrv_SelectBitmap
, /* pSelectBitmap */
3128 xrenderdrv_SelectBrush
, /* pSelectBrush */
3129 NULL
, /* pSelectClipPath */
3130 xrenderdrv_SelectFont
, /* pSelectFont */
3131 NULL
, /* pSelectPalette */
3132 NULL
, /* pSelectPen */
3133 NULL
, /* pSetArcDirection */
3134 NULL
, /* pSetBkColor */
3135 NULL
, /* pSetBkMode */
3136 NULL
, /* pSetDCBrushColor */
3137 NULL
, /* pSetDCPenColor */
3138 NULL
, /* pSetDIBColorTable */
3139 NULL
, /* pSetDIBitsToDevice */
3140 xrenderdrv_SetDeviceClipping
, /* pSetDeviceClipping */
3141 NULL
, /* pSetDeviceGammaRamp */
3142 NULL
, /* pSetLayout */
3143 NULL
, /* pSetMapMode */
3144 NULL
, /* pSetMapperFlags */
3145 NULL
, /* pSetPixel */
3146 NULL
, /* pSetPixelFormat */
3147 NULL
, /* pSetPolyFillMode */
3148 NULL
, /* pSetROP2 */
3149 NULL
, /* pSetRelAbs */
3150 NULL
, /* pSetStretchBltMode */
3151 NULL
, /* pSetTextAlign */
3152 NULL
, /* pSetTextCharacterExtra */
3153 NULL
, /* pSetTextColor */
3154 NULL
, /* pSetTextJustification */
3155 NULL
, /* pSetViewportExt */
3156 NULL
, /* pSetViewportOrg */
3157 NULL
, /* pSetWindowExt */
3158 NULL
, /* pSetWindowOrg */
3159 NULL
, /* pSetWorldTransform */
3160 NULL
, /* pStartDoc */
3161 NULL
, /* pStartPage */
3162 xrenderdrv_StretchBlt
, /* pStretchBlt */
3163 NULL
, /* pStretchDIBits */
3164 NULL
, /* pStrokeAndFillPath */
3165 NULL
, /* pStrokePath */
3166 NULL
, /* pSwapBuffers */
3167 NULL
, /* pUnrealizePalette */
3168 NULL
, /* pWidenPath */
3169 /* OpenGL not supported */
3172 #else /* SONAME_LIBXRENDER */
3174 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
3176 TRACE("XRender support not compiled in.\n");
3180 void X11DRV_XRender_Finalize(void)
3184 BOOL
X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP
*physBitmap
, int bits_pixel
, const DIBSECTION
*dib
)
3189 #endif /* SONAME_LIBXRENDER */