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
, BOOL use_alpha
)
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 if (info
->bmiHeader
.biBitCount
== 16) return WXR_FORMAT_X1R5G5B5
;
543 return use_alpha
? WXR_FORMAT_A8R8G8B8
: WXR_FORMAT_X8R8G8B8
;
545 return WXR_INVALID_FORMAT
;
548 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
549 static void set_xrender_transformation(Picture src_pict
, double xscale
, double yscale
, int xoffset
, int yoffset
)
551 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
552 XTransform xform
= {{
553 { XDoubleToFixed(xscale
), XDoubleToFixed(0), XDoubleToFixed(xoffset
) },
554 { XDoubleToFixed(0), XDoubleToFixed(yscale
), XDoubleToFixed(yoffset
) },
555 { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
558 pXRenderSetPictureTransform(gdi_display
, src_pict
, &xform
);
562 /* check if we can use repeating instead of scaling for the specified source DC */
563 static BOOL
use_source_repeat( struct xrender_physdev
*dev
)
565 return (dev
->x11dev
->bitmap
&&
566 dev
->x11dev
->drawable_rect
.right
- dev
->x11dev
->drawable_rect
.left
== 1 &&
567 dev
->x11dev
->drawable_rect
.bottom
- dev
->x11dev
->drawable_rect
.top
== 1);
570 static Picture
get_xrender_picture( struct xrender_physdev
*dev
, HRGN clip_rgn
, const RECT
*clip_rect
)
572 if (!dev
->pict
&& dev
->pict_format
)
574 XRenderPictureAttributes pa
;
577 pa
.subwindow_mode
= IncludeInferiors
;
578 dev
->pict
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
579 dev
->pict_format
, CPSubwindowMode
, &pa
);
581 TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
582 dev
->pict
, dev
->dev
.hdc
, dev
->x11dev
->drawable
);
583 dev
->update_clip
= TRUE
;
586 if (dev
->update_clip
)
593 rgn
= CreateRectRgnIndirect( clip_rect
);
594 if (clip_rgn
) CombineRgn( rgn
, rgn
, clip_rgn
, RGN_AND
);
595 CombineRgn( rgn
, rgn
, dev
->x11dev
->region
, RGN_AND
);
599 rgn
= CreateRectRgn( 0, 0, 0, 0 );
600 CombineRgn( rgn
, clip_rgn
, dev
->x11dev
->region
, RGN_AND
);
603 if ((clip_data
= X11DRV_GetRegionData( rgn
? rgn
: dev
->x11dev
->region
, 0 )))
606 pXRenderSetPictureClipRectangles( gdi_display
, dev
->pict
,
607 dev
->x11dev
->dc_rect
.left
, dev
->x11dev
->dc_rect
.top
,
608 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
610 HeapFree( GetProcessHeap(), 0, clip_data
);
612 dev
->update_clip
= (rgn
!= 0); /* have to update again if we are using a custom region */
613 if (rgn
) DeleteObject( rgn
);
618 static Picture
get_xrender_picture_source( struct xrender_physdev
*dev
, BOOL repeat
)
620 if (!dev
->pict_src
&& dev
->pict_format
)
622 XRenderPictureAttributes pa
;
625 pa
.subwindow_mode
= IncludeInferiors
;
626 pa
.repeat
= repeat
? RepeatNormal
: RepeatNone
;
627 dev
->pict_src
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
628 dev
->pict_format
, CPSubwindowMode
|CPRepeat
, &pa
);
631 TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
632 dev
->pict_src
, dev
->dev
.hdc
, dev
->x11dev
->drawable
, pa
.repeat
);
635 return dev
->pict_src
;
638 static void free_xrender_picture( struct xrender_physdev
*dev
)
640 if (dev
->pict
|| dev
->pict_src
)
643 XFlush( gdi_display
);
646 TRACE("freeing pict = %lx dc = %p\n", dev
->pict
, dev
->dev
.hdc
);
647 pXRenderFreePicture(gdi_display
, dev
->pict
);
652 TRACE("freeing pict = %lx dc = %p\n", dev
->pict_src
, dev
->dev
.hdc
);
653 pXRenderFreePicture(gdi_display
, dev
->pict_src
);
660 /* return a mask picture used to force alpha to 0 */
661 static Picture
get_no_alpha_mask(void)
663 static Pixmap pixmap
;
669 XRenderPictureAttributes pa
;
672 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
673 pa
.repeat
= RepeatNormal
;
674 pa
.component_alpha
= True
;
675 pict
= pXRenderCreatePicture( gdi_display
, pixmap
, pict_formats
[WXR_FORMAT_A8R8G8B8
],
676 CPRepeat
|CPComponentAlpha
, &pa
);
677 col
.red
= col
.green
= col
.blue
= 0xffff;
679 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
685 static BOOL
fontcmp(LFANDSIZE
*p1
, LFANDSIZE
*p2
)
687 if(p1
->hash
!= p2
->hash
) return TRUE
;
688 if(memcmp(&p1
->devsize
, &p2
->devsize
, sizeof(p1
->devsize
))) return TRUE
;
689 if(memcmp(&p1
->xform
, &p2
->xform
, sizeof(p1
->xform
))) return TRUE
;
690 if(memcmp(&p1
->lf
, &p2
->lf
, offsetof(LOGFONTW
, lfFaceName
))) return TRUE
;
691 return strcmpiW(p1
->lf
.lfFaceName
, p2
->lf
.lfFaceName
);
695 static void walk_cache(void)
699 EnterCriticalSection(&xrender_cs
);
700 for(i
=mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
701 TRACE("item %d\n", i
);
702 LeaveCriticalSection(&xrender_cs
);
706 static int LookupEntry(LFANDSIZE
*plfsz
)
710 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
712 if(glyphsetCache
[i
].count
== -1) break; /* reached free list so stop */
714 if(!fontcmp(&glyphsetCache
[i
].lfsz
, plfsz
)) {
715 glyphsetCache
[i
].count
++;
717 glyphsetCache
[prev_i
].next
= glyphsetCache
[i
].next
;
718 glyphsetCache
[i
].next
= mru
;
721 TRACE("found font in cache %d\n", i
);
726 TRACE("font not in cache\n");
730 static void FreeEntry(int entry
)
734 for(format
= 0; format
< AA_MAXVALUE
; format
++) {
735 gsCacheEntryFormat
* formatEntry
;
737 if( !glyphsetCache
[entry
].format
[format
] )
740 formatEntry
= glyphsetCache
[entry
].format
[format
];
742 if(formatEntry
->glyphset
) {
744 pXRenderFreeGlyphSet(gdi_display
, formatEntry
->glyphset
);
746 formatEntry
->glyphset
= 0;
748 if(formatEntry
->nrealized
) {
749 HeapFree(GetProcessHeap(), 0, formatEntry
->realized
);
750 formatEntry
->realized
= NULL
;
751 if(formatEntry
->bitmaps
) {
752 for(i
= 0; i
< formatEntry
->nrealized
; i
++)
753 HeapFree(GetProcessHeap(), 0, formatEntry
->bitmaps
[i
]);
754 HeapFree(GetProcessHeap(), 0, formatEntry
->bitmaps
);
755 formatEntry
->bitmaps
= NULL
;
757 HeapFree(GetProcessHeap(), 0, formatEntry
->gis
);
758 formatEntry
->gis
= NULL
;
759 formatEntry
->nrealized
= 0;
762 HeapFree(GetProcessHeap(), 0, formatEntry
);
763 glyphsetCache
[entry
].format
[format
] = NULL
;
767 static int AllocEntry(void)
769 int best
= -1, prev_best
= -1, i
, prev_i
= -1;
772 assert(glyphsetCache
[lastfree
].count
== -1);
773 glyphsetCache
[lastfree
].count
= 1;
775 lastfree
= glyphsetCache
[lastfree
].next
;
777 glyphsetCache
[best
].next
= mru
;
780 TRACE("empty space at %d, next lastfree = %d\n", mru
, lastfree
);
784 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
785 if(glyphsetCache
[i
].count
== 0) {
793 TRACE("freeing unused glyphset at cache %d\n", best
);
795 glyphsetCache
[best
].count
= 1;
797 glyphsetCache
[prev_best
].next
= glyphsetCache
[best
].next
;
798 glyphsetCache
[best
].next
= mru
;
806 TRACE("Growing cache\n");
809 glyphsetCache
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
811 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
812 * sizeof(*glyphsetCache
));
814 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
815 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
816 * sizeof(*glyphsetCache
));
818 for(best
= i
= glyphsetCacheSize
; i
< glyphsetCacheSize
+ INIT_CACHE_SIZE
;
820 glyphsetCache
[i
].next
= i
+ 1;
821 glyphsetCache
[i
].count
= -1;
823 glyphsetCache
[i
-1].next
= -1;
824 glyphsetCacheSize
+= INIT_CACHE_SIZE
;
826 lastfree
= glyphsetCache
[best
].next
;
827 glyphsetCache
[best
].count
= 1;
828 glyphsetCache
[best
].next
= mru
;
830 TRACE("new free cache slot at %d\n", mru
);
834 static BOOL
get_gasp_flags(HDC hdc
, WORD
*flags
)
844 size
= GetFontData(hdc
, MS_GASP_TAG
, 0, NULL
, 0);
845 if(size
== GDI_ERROR
)
848 gasp
= buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
849 GetFontData(hdc
, MS_GASP_TAG
, 0, gasp
, size
);
851 GetTextMetricsW(hdc
, &tm
);
852 ppem
= abs(X11DRV_YWStoDS(hdc
, tm
.tmAscent
+ tm
.tmDescent
- tm
.tmInternalLeading
));
855 num_recs
= get_be_word(*gasp
);
859 *flags
= get_be_word(*(gasp
+ 1));
860 if(ppem
<= get_be_word(*gasp
))
864 TRACE("got flags %04x for ppem %d\n", *flags
, ppem
);
866 HeapFree(GetProcessHeap(), 0, buffer
);
870 static AA_Type
get_antialias_type( HDC hdc
, BOOL subpixel
, BOOL hinter
)
874 UINT font_smoothing_type
, font_smoothing_orientation
;
876 if (X11DRV_XRender_Installed
&& subpixel
&&
877 SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE
, 0, &font_smoothing_type
, 0) &&
878 font_smoothing_type
== FE_FONTSMOOTHINGCLEARTYPE
)
880 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION
, 0,
881 &font_smoothing_orientation
, 0) &&
882 font_smoothing_orientation
== FE_FONTSMOOTHINGORIENTATIONBGR
)
889 If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
890 But, Wine's subpixel rendering can support the portrait mode.
893 else if (!hinter
|| !get_gasp_flags(hdc
, &flags
) || flags
& GASP_DOGRAY
)
901 static int GetCacheEntry( HDC hdc
, LFANDSIZE
*plfsz
)
906 static int hinter
= -1;
907 static int subpixel
= -1;
910 if((ret
= LookupEntry(plfsz
)) != -1) return ret
;
913 entry
= glyphsetCache
+ ret
;
914 entry
->lfsz
= *plfsz
;
915 for( format
= 0; format
< AA_MAXVALUE
; format
++ ) {
916 assert( !entry
->format
[format
] );
919 if(antialias
&& plfsz
->lf
.lfQuality
!= NONANTIALIASED_QUALITY
)
921 if(hinter
== -1 || subpixel
== -1)
923 RASTERIZER_STATUS status
;
924 GetRasterizerCaps(&status
, sizeof(status
));
925 hinter
= status
.wFlags
& WINE_TT_HINTER_ENABLED
;
926 subpixel
= status
.wFlags
& WINE_TT_SUBPIXEL_RENDERING_ENABLED
;
929 switch (plfsz
->lf
.lfQuality
)
931 case ANTIALIASED_QUALITY
:
932 entry
->aa_default
= get_antialias_type( hdc
, FALSE
, hinter
);
933 return ret
; /* ignore further configuration */
934 case CLEARTYPE_QUALITY
:
935 case CLEARTYPE_NATURAL_QUALITY
:
936 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
938 case DEFAULT_QUALITY
:
942 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING
, 0, &font_smoothing
, 0) &&
945 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
948 entry
->aa_default
= AA_None
;
952 font_smoothing
= TRUE
; /* default to enabled */
953 #ifdef SONAME_LIBFONTCONFIG
954 if (fontconfig_installed
)
956 FcPattern
*match
, *pattern
= pFcPatternCreate();
958 char family
[LF_FACESIZE
* 4];
960 WideCharToMultiByte( CP_UTF8
, 0, plfsz
->lf
.lfFaceName
, -1, family
, sizeof(family
), NULL
, NULL
);
961 pFcPatternAddString( pattern
, FC_FAMILY
, (FcChar8
*)family
);
962 if (plfsz
->lf
.lfWeight
!= FW_DONTCARE
)
965 switch (plfsz
->lf
.lfWeight
)
967 case FW_THIN
: weight
= FC_WEIGHT_THIN
; break;
968 case FW_EXTRALIGHT
: weight
= FC_WEIGHT_EXTRALIGHT
; break;
969 case FW_LIGHT
: weight
= FC_WEIGHT_LIGHT
; break;
970 case FW_NORMAL
: weight
= FC_WEIGHT_NORMAL
; break;
971 case FW_MEDIUM
: weight
= FC_WEIGHT_MEDIUM
; break;
972 case FW_SEMIBOLD
: weight
= FC_WEIGHT_SEMIBOLD
; break;
973 case FW_BOLD
: weight
= FC_WEIGHT_BOLD
; break;
974 case FW_EXTRABOLD
: weight
= FC_WEIGHT_EXTRABOLD
; break;
975 case FW_HEAVY
: weight
= FC_WEIGHT_HEAVY
; break;
976 default: weight
= (plfsz
->lf
.lfWeight
- 80) / 4; break;
978 pFcPatternAddInteger( pattern
, FC_WEIGHT
, weight
);
980 pFcPatternAddInteger( pattern
, FC_SLANT
, plfsz
->lf
.lfItalic
? FC_SLANT_ITALIC
: FC_SLANT_ROMAN
);
981 pFcConfigSubstitute( NULL
, pattern
, FcMatchPattern
);
982 pFcDefaultSubstitute( pattern
);
983 if ((match
= pFcFontMatch( NULL
, pattern
, &result
)))
988 if (pFcPatternGetBool( match
, FC_ANTIALIAS
, 0, &antialias
) != FcResultMatch
)
990 if (pFcPatternGetInteger( match
, FC_RGBA
, 0, &rgba
) == FcResultMatch
)
993 if (pFcPatternGetString( match
, FC_FILE
, 0, &file
) != FcResultMatch
) file
= NULL
;
995 TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
996 rgba
, antialias
, debugstr_w(plfsz
->lf
.lfFaceName
), debugstr_a((char *)file
) );
1000 case FC_RGBA_RGB
: entry
->aa_default
= AA_RGB
; break;
1001 case FC_RGBA_BGR
: entry
->aa_default
= AA_BGR
; break;
1002 case FC_RGBA_VRGB
: entry
->aa_default
= AA_VRGB
; break;
1003 case FC_RGBA_VBGR
: entry
->aa_default
= AA_VBGR
; break;
1004 case FC_RGBA_NONE
: entry
->aa_default
= AA_Grey
; break;
1007 if (!antialias
) font_smoothing
= FALSE
;
1008 pFcPatternDestroy( match
);
1010 pFcPatternDestroy( pattern
);
1012 #endif /* SONAME_LIBFONTCONFIG */
1014 /* now check Xft resources */
1017 BOOL antialias
= TRUE
;
1020 if ((value
= XGetDefault( gdi_display
, "Xft", "antialias" )))
1022 if (tolower(value
[0]) == 'f' || tolower(value
[0]) == 'n' ||
1023 value
[0] == '0' || !strcasecmp( value
, "off" ))
1026 if ((value
= XGetDefault( gdi_display
, "Xft", "rgba" )))
1028 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value
, antialias
);
1029 if (!strcmp( value
, "rgb" )) entry
->aa_default
= AA_RGB
;
1030 else if (!strcmp( value
, "bgr" )) entry
->aa_default
= AA_BGR
;
1031 else if (!strcmp( value
, "vrgb" )) entry
->aa_default
= AA_VRGB
;
1032 else if (!strcmp( value
, "vbgr" )) entry
->aa_default
= AA_VBGR
;
1033 else if (!strcmp( value
, "none" )) entry
->aa_default
= AA_Grey
;
1035 wine_tsx11_unlock();
1036 if (!antialias
) font_smoothing
= FALSE
;
1039 if (!font_smoothing
) entry
->aa_default
= AA_None
;
1041 /* we can't support subpixel without xrender */
1042 if (!X11DRV_XRender_Installed
&& entry
->aa_default
> AA_Grey
) entry
->aa_default
= AA_Grey
;
1045 entry
->aa_default
= AA_None
;
1050 static void dec_ref_cache(int index
)
1053 TRACE("dec'ing entry %d to %d\n", index
, glyphsetCache
[index
].count
- 1);
1054 assert(glyphsetCache
[index
].count
> 0);
1055 glyphsetCache
[index
].count
--;
1058 static void lfsz_calc_hash(LFANDSIZE
*plfsz
)
1060 DWORD hash
= 0, *ptr
, two_chars
;
1064 hash
^= plfsz
->devsize
.cx
;
1065 hash
^= plfsz
->devsize
.cy
;
1066 for(i
= 0, ptr
= (DWORD
*)&plfsz
->xform
; i
< sizeof(XFORM
)/sizeof(DWORD
); i
++, ptr
++)
1068 for(i
= 0, ptr
= (DWORD
*)&plfsz
->lf
; i
< 7; i
++, ptr
++)
1070 for(i
= 0, ptr
= (DWORD
*)plfsz
->lf
.lfFaceName
; i
< LF_FACESIZE
/2; i
++, ptr
++) {
1072 pwc
= (WCHAR
*)&two_chars
;
1074 *pwc
= toupperW(*pwc
);
1076 *pwc
= toupperW(*pwc
);
1084 /***********************************************************************
1085 * X11DRV_XRender_Finalize
1087 void X11DRV_XRender_Finalize(void)
1091 EnterCriticalSection(&xrender_cs
);
1092 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
1094 LeaveCriticalSection(&xrender_cs
);
1097 /**********************************************************************
1098 * xrenderdrv_SelectFont
1100 static HFONT
xrenderdrv_SelectFont( PHYSDEV dev
, HFONT hfont
, HANDLE gdiFont
)
1102 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1105 if (!GetObjectW( hfont
, sizeof(lfsz
.lf
), &lfsz
.lf
)) return HGDI_ERROR
;
1109 dev
= GET_NEXT_PHYSDEV( dev
, pSelectFont
);
1110 return dev
->funcs
->pSelectFont( dev
, hfont
, gdiFont
);
1113 TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1114 lfsz
.lf
.lfHeight
, lfsz
.lf
.lfWidth
, lfsz
.lf
.lfWeight
,
1115 lfsz
.lf
.lfItalic
, lfsz
.lf
.lfCharSet
, debugstr_w(lfsz
.lf
.lfFaceName
));
1116 lfsz
.lf
.lfWidth
= abs( lfsz
.lf
.lfWidth
);
1117 lfsz
.devsize
.cx
= X11DRV_XWStoDS( dev
->hdc
, lfsz
.lf
.lfWidth
);
1118 lfsz
.devsize
.cy
= X11DRV_YWStoDS( dev
->hdc
, lfsz
.lf
.lfHeight
);
1120 GetTransform( dev
->hdc
, 0x204, &lfsz
.xform
);
1121 TRACE("font transform %f %f %f %f\n", lfsz
.xform
.eM11
, lfsz
.xform
.eM12
,
1122 lfsz
.xform
.eM21
, lfsz
.xform
.eM22
);
1124 /* Not used fields, would break hashing */
1125 lfsz
.xform
.eDx
= lfsz
.xform
.eDy
= 0;
1127 lfsz_calc_hash(&lfsz
);
1129 EnterCriticalSection(&xrender_cs
);
1130 if (physdev
->cache_index
!= -1)
1131 dec_ref_cache( physdev
->cache_index
);
1132 physdev
->cache_index
= GetCacheEntry( dev
->hdc
, &lfsz
);
1133 LeaveCriticalSection(&xrender_cs
);
1134 physdev
->x11dev
->has_gdi_font
= TRUE
;
1138 static BOOL
create_xrender_dc( PHYSDEV
*pdev
, enum wxr_format format
)
1140 X11DRV_PDEVICE
*x11dev
= get_x11drv_dev( *pdev
);
1141 struct xrender_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
1143 if (!physdev
) return FALSE
;
1144 physdev
->x11dev
= x11dev
;
1145 physdev
->cache_index
= -1;
1146 physdev
->format
= format
;
1147 physdev
->pict_format
= pict_formats
[format
];
1148 push_dc_driver( pdev
, &physdev
->dev
, &xrender_funcs
);
1152 /* store the color mask data in the bitmap info structure */
1153 static void set_color_info( XRenderPictFormat
*format
, BITMAPINFO
*info
)
1155 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1157 info
->bmiHeader
.biPlanes
= 1;
1158 info
->bmiHeader
.biBitCount
= pixmap_formats
[format
->depth
]->bits_per_pixel
;
1159 info
->bmiHeader
.biCompression
= BI_RGB
;
1160 info
->bmiHeader
.biClrUsed
= 0;
1162 switch (info
->bmiHeader
.biBitCount
)
1165 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1166 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1167 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1168 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1171 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1172 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1173 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1174 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1175 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1181 /**********************************************************************
1182 * xrenderdrv_CreateDC
1184 static BOOL
xrenderdrv_CreateDC( PHYSDEV
*pdev
, LPCWSTR driver
, LPCWSTR device
,
1185 LPCWSTR output
, const DEVMODEW
* initData
)
1187 return create_xrender_dc( pdev
, default_format
);
1190 /**********************************************************************
1191 * xrenderdrv_CreateCompatibleDC
1193 static BOOL
xrenderdrv_CreateCompatibleDC( PHYSDEV orig
, PHYSDEV
*pdev
)
1195 if (orig
) /* chain to x11drv first */
1197 orig
= GET_NEXT_PHYSDEV( orig
, pCreateCompatibleDC
);
1198 if (!orig
->funcs
->pCreateCompatibleDC( orig
, pdev
)) return FALSE
;
1200 /* otherwise we have been called by x11drv */
1202 return create_xrender_dc( pdev
, WXR_FORMAT_MONO
);
1205 /**********************************************************************
1206 * xrenderdrv_DeleteDC
1208 static BOOL
xrenderdrv_DeleteDC( PHYSDEV dev
)
1210 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1212 free_xrender_picture( physdev
);
1214 EnterCriticalSection( &xrender_cs
);
1215 if (physdev
->cache_index
!= -1) dec_ref_cache( physdev
->cache_index
);
1216 LeaveCriticalSection( &xrender_cs
);
1218 HeapFree( GetProcessHeap(), 0, physdev
);
1222 /**********************************************************************
1223 * xrenderdrv_ExtEscape
1225 static INT
xrenderdrv_ExtEscape( PHYSDEV dev
, INT escape
, INT in_count
, LPCVOID in_data
,
1226 INT out_count
, LPVOID out_data
)
1228 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1230 dev
= GET_NEXT_PHYSDEV( dev
, pExtEscape
);
1232 if (escape
== X11DRV_ESCAPE
&& in_data
&& in_count
>= sizeof(enum x11drv_escape_codes
))
1234 if (*(const enum x11drv_escape_codes
*)in_data
== X11DRV_SET_DRAWABLE
)
1236 BOOL ret
= dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1237 if (ret
) free_xrender_picture( physdev
); /* pict format doesn't change, only drawable */
1241 return dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1244 /****************************************************************************
1245 * xrenderdrv_CreateBitmap
1247 static BOOL
xrenderdrv_CreateBitmap( PHYSDEV dev
, HBITMAP hbitmap
)
1249 enum wxr_format format
= WXR_INVALID_FORMAT
;
1252 if (!GetObjectW( hbitmap
, sizeof(bitmap
), &bitmap
)) return FALSE
;
1254 if (bitmap
.bmPlanes
== 1 && bitmap
.bmBitsPixel
== screen_bpp
)
1256 switch (bitmap
.bmBitsPixel
)
1258 case 16: format
= WXR_FORMAT_R5G6B5
; break;
1259 case 24: format
= WXR_FORMAT_R8G8B8
; break;
1260 case 32: format
= WXR_FORMAT_A8R8G8B8
; break;
1264 if (pict_formats
[format
])
1265 return X11DRV_create_phys_bitmap( hbitmap
, &bitmap
, pict_formats
[format
]->depth
,
1266 TRUE
, &wxr_color_shifts
[format
] );
1268 dev
= GET_NEXT_PHYSDEV( dev
, pCreateBitmap
);
1269 return dev
->funcs
->pCreateBitmap( dev
, hbitmap
);
1272 /****************************************************************************
1273 * xrenderdrv_DeleteBitmap
1275 static BOOL
xrenderdrv_DeleteBitmap( HBITMAP hbitmap
)
1277 return X11DRV_DeleteBitmap( hbitmap
);
1280 /***********************************************************************
1281 * xrenderdrv_SelectBitmap
1283 static HBITMAP
xrenderdrv_SelectBitmap( PHYSDEV dev
, HBITMAP hbitmap
)
1286 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1288 dev
= GET_NEXT_PHYSDEV( dev
, pSelectBitmap
);
1289 ret
= dev
->funcs
->pSelectBitmap( dev
, hbitmap
);
1292 free_xrender_picture( physdev
);
1293 physdev
->format
= get_xrender_format_from_color_shifts( physdev
->x11dev
->depth
,
1294 physdev
->x11dev
->color_shifts
);
1295 physdev
->pict_format
= pict_formats
[physdev
->format
];
1300 /***********************************************************************
1301 * xrenderdrv_GetImage
1303 static DWORD
xrenderdrv_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1304 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
1306 if (hbitmap
) return X11DRV_GetImage( dev
, hbitmap
, info
, bits
, src
);
1307 dev
= GET_NEXT_PHYSDEV( dev
, pGetImage
);
1308 return dev
->funcs
->pGetImage( dev
, hbitmap
, info
, bits
, src
);
1311 /***********************************************************************
1312 * xrenderdrv_SetDeviceClipping
1314 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev
, HRGN vis_rgn
, HRGN clip_rgn
)
1316 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1318 physdev
->update_clip
= TRUE
;
1320 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
1321 dev
->funcs
->pSetDeviceClipping( dev
, vis_rgn
, clip_rgn
);
1325 BOOL
X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP
*physBitmap
, int bits_pixel
, const DIBSECTION
*dib
)
1327 XRenderPictFormat
*pict_format
;
1329 const DWORD
*bitfields
;
1330 static const DWORD bitfields_32
[3] = {0xff0000, 0x00ff00, 0x0000ff};
1331 static const DWORD bitfields_16
[3] = {0x7c00, 0x03e0, 0x001f};
1334 /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1335 * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1336 * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1337 if (!X11DRV_XRender_Installed
|| bits_pixel
<= 8)
1340 if(dib
->dsBmih
.biCompression
== BI_BITFIELDS
)
1341 bitfields
= dib
->dsBitfields
;
1342 else if(bits_pixel
== 24 || bits_pixel
== 32)
1343 bitfields
= bitfields_32
;
1345 bitfields
= bitfields_16
;
1347 X11DRV_PALETTE_ComputeColorShifts(&shifts
, bitfields
[0], bitfields
[1], bitfields
[2]);
1348 pict_format
= pict_formats
[get_xrender_format_from_color_shifts(dib
->dsBm
.bmBitsPixel
, &shifts
)];
1350 /* Common formats should be in our picture format table. */
1353 TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1354 dib
->dsBm
.bmBitsPixel
, bitfields
[0], bitfields
[1], bitfields
[2]);
1358 physBitmap
->depth
= pict_format
->depth
;
1359 physBitmap
->trueColor
= TRUE
;
1360 physBitmap
->color_shifts
= shifts
;
1364 /************************************************************************
1367 * Helper to ExtTextOut. Must be called inside xrender_cs
1369 static void UploadGlyph(struct xrender_physdev
*physDev
, int glyph
, AA_Type format
)
1371 unsigned int buflen
;
1376 gsCacheEntry
*entry
= glyphsetCache
+ physDev
->cache_index
;
1377 gsCacheEntryFormat
*formatEntry
;
1378 UINT ggo_format
= GGO_GLYPH_INDEX
;
1379 enum wxr_format wxr_format
;
1380 static const char zero
[4];
1381 static const MAT2 identity
= { {0,1},{0,0},{0,0},{0,1} };
1385 ggo_format
|= WINE_GGO_GRAY16_BITMAP
;
1388 ggo_format
|= WINE_GGO_HRGB_BITMAP
;
1391 ggo_format
|= WINE_GGO_HBGR_BITMAP
;
1394 ggo_format
|= WINE_GGO_VRGB_BITMAP
;
1397 ggo_format
|= WINE_GGO_VBGR_BITMAP
;
1401 ERR("aa = %d - not implemented\n", format
);
1403 ggo_format
|= GGO_BITMAP
;
1407 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1408 if(buflen
== GDI_ERROR
) {
1409 if(format
!= AA_None
) {
1411 entry
->aa_default
= AA_None
;
1412 ggo_format
= GGO_GLYPH_INDEX
| GGO_BITMAP
;
1413 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1415 if(buflen
== GDI_ERROR
) {
1416 WARN("GetGlyphOutlineW failed using default glyph\n");
1417 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0, ggo_format
, &gm
, 0, NULL
, &identity
);
1418 if(buflen
== GDI_ERROR
) {
1419 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1420 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0x20, ggo_format
, &gm
, 0, NULL
, &identity
);
1421 if(buflen
== GDI_ERROR
) {
1422 ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1427 TRACE("Turning off antialiasing for this monochrome font\n");
1430 /* If there is nothing for the current type, we create the entry. */
1431 if( !entry
->format
[format
] ) {
1432 entry
->format
[format
] = HeapAlloc(GetProcessHeap(),
1434 sizeof(gsCacheEntryFormat
));
1436 formatEntry
= entry
->format
[format
];
1438 if(formatEntry
->nrealized
<= glyph
) {
1439 formatEntry
->nrealized
= (glyph
/ 128 + 1) * 128;
1441 if (formatEntry
->realized
)
1442 formatEntry
->realized
= HeapReAlloc(GetProcessHeap(),
1444 formatEntry
->realized
,
1445 formatEntry
->nrealized
* sizeof(BOOL
));
1447 formatEntry
->realized
= HeapAlloc(GetProcessHeap(),
1449 formatEntry
->nrealized
* sizeof(BOOL
));
1451 if(!X11DRV_XRender_Installed
) {
1452 if (formatEntry
->bitmaps
)
1453 formatEntry
->bitmaps
= HeapReAlloc(GetProcessHeap(),
1455 formatEntry
->bitmaps
,
1456 formatEntry
->nrealized
* sizeof(formatEntry
->bitmaps
[0]));
1458 formatEntry
->bitmaps
= HeapAlloc(GetProcessHeap(),
1460 formatEntry
->nrealized
* sizeof(formatEntry
->bitmaps
[0]));
1462 if (formatEntry
->gis
)
1463 formatEntry
->gis
= HeapReAlloc(GetProcessHeap(),
1466 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1468 formatEntry
->gis
= HeapAlloc(GetProcessHeap(),
1470 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1474 if(formatEntry
->glyphset
== 0 && X11DRV_XRender_Installed
) {
1477 wxr_format
= WXR_FORMAT_GRAY
;
1484 wxr_format
= WXR_FORMAT_A8R8G8B8
;
1488 ERR("aa = %d - not implemented\n", format
);
1490 wxr_format
= WXR_FORMAT_MONO
;
1495 formatEntry
->font_format
= pict_formats
[wxr_format
];
1496 formatEntry
->glyphset
= pXRenderCreateGlyphSet(gdi_display
, formatEntry
->font_format
);
1497 wine_tsx11_unlock();
1501 buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buflen
);
1502 GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, buflen
, buf
, &identity
);
1503 formatEntry
->realized
[glyph
] = TRUE
;
1505 TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1507 gm
.gmBlackBoxX
, gm
.gmBlackBoxY
, gm
.gmCellIncX
, gm
.gmCellIncY
,
1508 gm
.gmptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.y
);
1510 gi
.width
= gm
.gmBlackBoxX
;
1511 gi
.height
= gm
.gmBlackBoxY
;
1512 gi
.x
= -gm
.gmptGlyphOrigin
.x
;
1513 gi
.y
= gm
.gmptGlyphOrigin
.y
;
1514 gi
.xOff
= gm
.gmCellIncX
;
1515 gi
.yOff
= gm
.gmCellIncY
;
1517 if(TRACE_ON(xrender
)) {
1520 unsigned char *line
;
1522 if(format
== AA_None
) {
1523 pitch
= ((gi
.width
+ 31) / 32) * 4;
1524 for(i
= 0; i
< gi
.height
; i
++) {
1525 line
= (unsigned char*) buf
+ i
* pitch
;
1527 for(j
= 0; j
< pitch
* 8; j
++) {
1528 strcat(output
, (line
[j
/ 8] & (1 << (7 - (j
% 8)))) ? "#" : " ");
1530 TRACE("%s\n", output
);
1533 static const char blks
[] = " .:;!o*#";
1537 pitch
= ((gi
.width
+ 3) / 4) * 4;
1538 for(i
= 0; i
< gi
.height
; i
++) {
1539 line
= (unsigned char*) buf
+ i
* pitch
;
1541 for(j
= 0; j
< pitch
; j
++) {
1542 str
[0] = blks
[line
[j
] >> 5];
1543 strcat(output
, str
);
1545 TRACE("%s\n", output
);
1551 if(formatEntry
->glyphset
) {
1552 if(format
== AA_None
&& BitmapBitOrder(gdi_display
) != MSBFirst
) {
1553 unsigned char *byte
= (unsigned char*) buf
, c
;
1559 /* magic to flip bit order */
1560 c
= ((c
<< 1) & 0xaa) | ((c
>> 1) & 0x55);
1561 c
= ((c
<< 2) & 0xcc) | ((c
>> 2) & 0x33);
1562 c
= ((c
<< 4) & 0xf0) | ((c
>> 4) & 0x0f);
1567 else if ( format
!= AA_Grey
&&
1568 ImageByteOrder (gdi_display
) != NATIVE_BYTE_ORDER
)
1570 unsigned int i
, *data
= (unsigned int *)buf
;
1571 for (i
= buflen
/ sizeof(int); i
; i
--, data
++) *data
= RtlUlongByteSwap(*data
);
1576 XRenderCompositeText seems to ignore 0x0 glyphs when
1577 AA_None, which means we lose the advance width of glyphs
1578 like the space. We'll pretend that such glyphs are 1x1
1583 gi
.width
= gi
.height
= 1;
1586 pXRenderAddGlyphs(gdi_display
, formatEntry
->glyphset
, &gid
, &gi
, 1,
1587 buflen
? buf
: zero
, buflen
? buflen
: sizeof(zero
));
1588 wine_tsx11_unlock();
1589 HeapFree(GetProcessHeap(), 0, buf
);
1591 formatEntry
->bitmaps
[glyph
] = buf
;
1594 formatEntry
->gis
[glyph
] = gi
;
1597 static void SharpGlyphMono(struct xrender_physdev
*physDev
, INT x
, INT y
,
1598 void *bitmap
, XGlyphInfo
*gi
)
1600 unsigned char *srcLine
= bitmap
, *src
;
1601 unsigned char bits
, bitsMask
;
1602 int width
= gi
->width
;
1603 int stride
= ((width
+ 31) & ~31) >> 3;
1604 int height
= gi
->height
;
1608 TRACE("%d, %d\n", x
, y
);
1617 bitsMask
= 0x80; /* FreeType is always MSB first */
1623 if (bits
& bitsMask
)
1631 bitsMask
= bitsMask
>> 1;
1637 } while (bits
& bitsMask
);
1638 XFillRectangle (gdi_display
, physDev
->x11dev
->drawable
,
1639 physDev
->x11dev
->gc
, xspan
, y
, lenspan
, 1);
1651 bitsMask
= bitsMask
>> 1;
1657 } while (!(bits
& bitsMask
));
1664 static void SharpGlyphGray(struct xrender_physdev
*physDev
, INT x
, INT y
,
1665 void *bitmap
, XGlyphInfo
*gi
)
1667 unsigned char *srcLine
= bitmap
, *src
, bits
;
1668 int width
= gi
->width
;
1669 int stride
= ((width
+ 3) & ~3);
1670 int height
= gi
->height
;
1695 } while (bits
>= 0x80);
1696 XFillRectangle (gdi_display
, physDev
->x11dev
->drawable
,
1697 physDev
->x11dev
->gc
, xspan
, y
, lenspan
, 1);
1710 } while (bits
< 0x80);
1718 static void ExamineBitfield (DWORD mask
, int *shift
, int *len
)
1723 while ((mask
& 1) == 0)
1729 while ((mask
& 1) == 1)
1738 static DWORD
GetField (DWORD pixel
, int shift
, int len
)
1740 pixel
= pixel
& (((1 << (len
)) - 1) << shift
);
1741 pixel
= pixel
<< (32 - (shift
+ len
)) >> 24;
1744 pixel
|= (pixel
>> len
);
1751 static DWORD
PutField (DWORD pixel
, int shift
, int len
)
1753 shift
= shift
- (8 - len
);
1755 pixel
&= (((1 << len
) - 1) << (8 - len
));
1763 static void SmoothGlyphGray(XImage
*image
, int x
, int y
, void *bitmap
, XGlyphInfo
*gi
,
1769 BYTE
*maskLine
, *mask
, m
;
1774 BYTE src_r
, src_g
, src_b
;
1779 height
= gi
->height
;
1782 maskStride
= (width
+ 3) & ~3;
1784 ExamineBitfield (image
->red_mask
, &r_shift
, &r_len
);
1785 ExamineBitfield (image
->green_mask
, &g_shift
, &g_len
);
1786 ExamineBitfield (image
->blue_mask
, &b_shift
, &b_len
);
1788 src_r
= GetField(color
, r_shift
, r_len
);
1789 src_g
= GetField(color
, g_shift
, g_len
);
1790 src_b
= GetField(color
, b_shift
, b_len
);
1792 for(; height
--; y
++)
1795 maskLine
+= maskStride
;
1800 if(y
>= image
->height
) break;
1804 if(tx
>= image
->width
) break;
1807 if(tx
< 0) continue;
1810 XPutPixel (image
, tx
, y
, color
);
1815 pixel
= XGetPixel (image
, tx
, y
);
1817 r
= GetField(pixel
, r_shift
, r_len
);
1818 r
= ((BYTE
)~m
* (WORD
)r
+ (BYTE
)m
* (WORD
)src_r
) >> 8;
1819 g
= GetField(pixel
, g_shift
, g_len
);
1820 g
= ((BYTE
)~m
* (WORD
)g
+ (BYTE
)m
* (WORD
)src_g
) >> 8;
1821 b
= GetField(pixel
, b_shift
, b_len
);
1822 b
= ((BYTE
)~m
* (WORD
)b
+ (BYTE
)m
* (WORD
)src_b
) >> 8;
1824 pixel
= (PutField (r
, r_shift
, r_len
) |
1825 PutField (g
, g_shift
, g_len
) |
1826 PutField (b
, b_shift
, b_len
));
1827 XPutPixel (image
, tx
, y
, pixel
);
1833 /*************************************************************
1836 * Returns an appropriate Picture for tiling the text colour.
1837 * Call and use result within the xrender_cs
1839 static Picture
get_tile_pict( enum wxr_format wxr_format
, const XRenderColor
*color
)
1845 XRenderColor current_color
;
1846 } tiles
[WXR_NB_FORMATS
], *tile
;
1848 tile
= &tiles
[wxr_format
];
1852 XRenderPictureAttributes pa
;
1853 XRenderPictFormat
*pict_format
= pict_formats
[wxr_format
];
1856 tile
->xpm
= XCreatePixmap(gdi_display
, root_window
, 1, 1, pict_format
->depth
);
1858 pa
.repeat
= RepeatNormal
;
1859 tile
->pict
= pXRenderCreatePicture(gdi_display
, tile
->xpm
, pict_format
, CPRepeat
, &pa
);
1860 wine_tsx11_unlock();
1862 /* init current_color to something different from text_pixel */
1863 tile
->current_color
= *color
;
1864 tile
->current_color
.red
^= 0xffff;
1866 if (wxr_format
== WXR_FORMAT_MONO
)
1868 /* for a 1bpp bitmap we always need a 1 in the tile */
1870 col
.red
= col
.green
= col
.blue
= 0;
1873 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, &col
, 0, 0, 1, 1);
1874 wine_tsx11_unlock();
1878 if (memcmp( color
, &tile
->current_color
, sizeof(*color
) ) && wxr_format
!= WXR_FORMAT_MONO
)
1881 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, color
, 0, 0, 1, 1);
1882 wine_tsx11_unlock();
1883 tile
->current_color
= *color
;
1888 /*************************************************************
1891 * Returns an appropriate Picture for masking with the specified alpha.
1892 * Call and use result within the xrender_cs
1894 static Picture
get_mask_pict( int alpha
)
1896 static Pixmap pixmap
;
1897 static Picture pict
;
1898 static int current_alpha
;
1900 if (alpha
== 0xffff) return 0; /* don't need a mask for alpha==1.0 */
1904 XRenderPictureAttributes pa
;
1907 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
1908 pa
.repeat
= RepeatNormal
;
1909 pict
= pXRenderCreatePicture( gdi_display
, pixmap
,
1910 pict_formats
[WXR_FORMAT_A8R8G8B8
], CPRepeat
, &pa
);
1911 wine_tsx11_unlock();
1915 if (alpha
!= current_alpha
)
1918 col
.red
= col
.green
= col
.blue
= 0;
1919 col
.alpha
= current_alpha
= alpha
;
1921 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
1922 wine_tsx11_unlock();
1927 static int XRenderErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
1932 /********************************************************************
1933 * is_dib_with_colortable
1935 * Return TRUE if physdev is backed by a dibsection with <= 8 bits per pixel
1937 static inline BOOL
is_dib_with_colortable( X11DRV_PDEVICE
*physDev
)
1941 if( physDev
->bitmap
&& GetObjectW( physDev
->bitmap
->hbitmap
, sizeof(dib
), &dib
) == sizeof(dib
) &&
1942 dib
.dsBmih
.biBitCount
<= 8 )
1948 /***********************************************************************
1949 * xrenderdrv_ExtTextOut
1951 static BOOL
xrenderdrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
,
1952 const RECT
*lprect
, LPCWSTR wstr
, UINT count
, const INT
*lpDx
)
1954 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1956 gsCacheEntry
*entry
;
1957 gsCacheEntryFormat
*formatEntry
;
1959 int textPixel
, backgroundPixel
;
1960 RGNDATA
*saved_region
= NULL
;
1961 BOOL disable_antialias
= FALSE
;
1962 AA_Type aa_type
= AA_None
;
1964 Picture tile_pict
= 0;
1966 if (!physdev
->x11dev
->has_gdi_font
)
1968 dev
= GET_NEXT_PHYSDEV( dev
, pExtTextOut
);
1969 return dev
->funcs
->pExtTextOut( dev
, x
, y
, flags
, lprect
, wstr
, count
, lpDx
);
1972 if(is_dib_with_colortable( physdev
->x11dev
))
1974 TRACE("Disabling antialiasing\n");
1975 disable_antialias
= TRUE
;
1978 xgcval
.function
= GXcopy
;
1979 xgcval
.background
= physdev
->x11dev
->backgroundPixel
;
1980 xgcval
.fill_style
= FillSolid
;
1982 XChangeGC( gdi_display
, physdev
->x11dev
->gc
, GCFunction
| GCBackground
| GCFillStyle
, &xgcval
);
1983 wine_tsx11_unlock();
1985 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
1987 if(physdev
->x11dev
->depth
== 1) {
1988 if((physdev
->x11dev
->textPixel
& 0xffffff) == 0) {
1990 backgroundPixel
= 1;
1993 backgroundPixel
= 0;
1996 textPixel
= physdev
->x11dev
->textPixel
;
1997 backgroundPixel
= physdev
->x11dev
->backgroundPixel
;
2000 if(flags
& ETO_OPAQUE
)
2003 XSetForeground( gdi_display
, physdev
->x11dev
->gc
, backgroundPixel
);
2004 XFillRectangle( gdi_display
, physdev
->x11dev
->drawable
, physdev
->x11dev
->gc
,
2005 physdev
->x11dev
->dc_rect
.left
+ lprect
->left
, physdev
->x11dev
->dc_rect
.top
+ lprect
->top
,
2006 lprect
->right
- lprect
->left
, lprect
->bottom
- lprect
->top
);
2007 wine_tsx11_unlock();
2016 EnterCriticalSection(&xrender_cs
);
2018 entry
= glyphsetCache
+ physdev
->cache_index
;
2019 if( disable_antialias
== FALSE
)
2020 aa_type
= entry
->aa_default
;
2021 formatEntry
= entry
->format
[aa_type
];
2023 for(idx
= 0; idx
< count
; idx
++) {
2024 if( !formatEntry
) {
2025 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
2026 /* re-evaluate antialias since aa_default may have changed */
2027 if( disable_antialias
== FALSE
)
2028 aa_type
= entry
->aa_default
;
2029 formatEntry
= entry
->format
[aa_type
];
2030 } else if( wstr
[idx
] >= formatEntry
->nrealized
|| formatEntry
->realized
[wstr
[idx
]] == FALSE
) {
2031 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
2036 WARN("could not upload requested glyphs\n");
2037 LeaveCriticalSection(&xrender_cs
);
2041 TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr
,count
),
2042 physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
2044 if(X11DRV_XRender_Installed
)
2046 XGlyphElt16
*elts
= HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16
) * count
);
2047 POINT offset
= {0, 0};
2048 POINT desired
, current
;
2049 int render_op
= PictOpOver
;
2050 Picture pict
= get_xrender_picture( physdev
, 0, (flags
& ETO_CLIPPED
) ? lprect
: NULL
);
2053 /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
2054 So we pass zeros to the function and move to our starting position using the first
2055 element of the elts array. */
2057 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
;
2058 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
;
2059 current
.x
= current
.y
= 0;
2061 get_xrender_color(physdev
->pict_format
, physdev
->x11dev
->textPixel
, &col
);
2062 tile_pict
= get_tile_pict(physdev
->format
, &col
);
2064 /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
2066 if((physdev
->format
== WXR_FORMAT_MONO
) && (textPixel
== 0))
2067 render_op
= PictOpOutReverse
; /* This gives us 'black' text */
2069 for(idx
= 0; idx
< count
; idx
++)
2071 elts
[idx
].glyphset
= formatEntry
->glyphset
;
2072 elts
[idx
].chars
= wstr
+ idx
;
2073 elts
[idx
].nchars
= 1;
2074 elts
[idx
].xOff
= desired
.x
- current
.x
;
2075 elts
[idx
].yOff
= desired
.y
- current
.y
;
2077 current
.x
+= (elts
[idx
].xOff
+ formatEntry
->gis
[wstr
[idx
]].xOff
);
2078 current
.y
+= (elts
[idx
].yOff
+ formatEntry
->gis
[wstr
[idx
]].yOff
);
2082 desired
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2083 desired
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2089 offset
.x
+= lpDx
[idx
* 2];
2090 offset
.y
+= lpDx
[idx
* 2 + 1];
2093 offset
.x
+= lpDx
[idx
];
2094 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
;
2095 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
;
2100 /* Make sure we don't have any transforms set from a previous call */
2101 set_xrender_transformation(pict
, 1, 1, 0, 0);
2102 pXRenderCompositeText16(gdi_display
, render_op
,
2105 formatEntry
->font_format
,
2106 0, 0, 0, 0, elts
, count
);
2107 wine_tsx11_unlock();
2108 HeapFree(GetProcessHeap(), 0, elts
);
2110 POINT offset
= {0, 0};
2112 if (flags
& ETO_CLIPPED
)
2114 HRGN clip_region
= CreateRectRgnIndirect( lprect
);
2115 saved_region
= add_extra_clipping_region( physdev
->x11dev
, clip_region
);
2116 DeleteObject( clip_region
);
2120 XSetForeground( gdi_display
, physdev
->x11dev
->gc
, textPixel
);
2122 if(aa_type
== AA_None
|| physdev
->x11dev
->depth
== 1)
2124 void (* sharp_glyph_fn
)(struct xrender_physdev
*, INT
, INT
, void *, XGlyphInfo
*);
2126 if(aa_type
== AA_None
)
2127 sharp_glyph_fn
= SharpGlyphMono
;
2129 sharp_glyph_fn
= SharpGlyphGray
;
2131 for(idx
= 0; idx
< count
; idx
++) {
2132 sharp_glyph_fn(physdev
,
2133 physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
,
2134 physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
,
2135 formatEntry
->bitmaps
[wstr
[idx
]],
2136 &formatEntry
->gis
[wstr
[idx
]]);
2141 offset
.x
+= lpDx
[idx
* 2];
2142 offset
.y
+= lpDx
[idx
* 2 + 1];
2145 offset
.x
+= lpDx
[idx
];
2149 offset
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2150 offset
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2155 int image_x
, image_y
, image_off_x
, image_off_y
, image_w
, image_h
;
2156 RECT extents
= {0, 0, 0, 0};
2158 int w
= physdev
->x11dev
->drawable_rect
.right
- physdev
->x11dev
->drawable_rect
.left
;
2159 int h
= physdev
->x11dev
->drawable_rect
.bottom
- physdev
->x11dev
->drawable_rect
.top
;
2161 TRACE("drawable %dx%d\n", w
, h
);
2163 for(idx
= 0; idx
< count
; idx
++) {
2164 if(extents
.left
> cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
)
2165 extents
.left
= cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
;
2166 if(extents
.top
> cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
)
2167 extents
.top
= cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
;
2168 if(extents
.right
< cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
+ formatEntry
->gis
[wstr
[idx
]].width
)
2169 extents
.right
= cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
+ formatEntry
->gis
[wstr
[idx
]].width
;
2170 if(extents
.bottom
< cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
+ formatEntry
->gis
[wstr
[idx
]].height
)
2171 extents
.bottom
= cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
+ formatEntry
->gis
[wstr
[idx
]].height
;
2177 cur
.x
+= lpDx
[idx
* 2];
2178 cur
.y
+= lpDx
[idx
* 2 + 1];
2185 cur
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2186 cur
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2189 TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents
.left
, extents
.top
,
2190 extents
.right
, extents
.bottom
, physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
2192 if(physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
>= 0) {
2193 image_x
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
;
2197 image_off_x
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
;
2199 if(physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
>= 0) {
2200 image_y
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
;
2204 image_off_y
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
;
2206 if(physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.right
< w
)
2207 image_w
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.right
- image_x
;
2209 image_w
= w
- image_x
;
2210 if(physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.bottom
< h
)
2211 image_h
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.bottom
- image_y
;
2213 image_h
= h
- image_y
;
2215 if(image_w
<= 0 || image_h
<= 0) goto no_image
;
2217 X11DRV_expect_error(gdi_display
, XRenderErrorHandler
, NULL
);
2218 image
= XGetImage(gdi_display
, physdev
->x11dev
->drawable
,
2219 image_x
, image_y
, image_w
, image_h
,
2220 AllPlanes
, ZPixmap
);
2221 X11DRV_check_error();
2223 TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2224 gdi_display
, (int)physdev
->x11dev
->drawable
, image_x
, image_y
,
2225 image_w
, image_h
, AllPlanes
, ZPixmap
,
2226 physdev
->x11dev
->depth
, image
);
2228 Pixmap xpm
= XCreatePixmap(gdi_display
, root_window
, image_w
, image_h
,
2229 physdev
->x11dev
->depth
);
2233 gcv
.graphics_exposures
= False
;
2234 gc
= XCreateGC(gdi_display
, xpm
, GCGraphicsExposures
, &gcv
);
2235 XCopyArea(gdi_display
, physdev
->x11dev
->drawable
, xpm
, gc
, image_x
, image_y
,
2236 image_w
, image_h
, 0, 0);
2237 XFreeGC(gdi_display
, gc
);
2238 X11DRV_expect_error(gdi_display
, XRenderErrorHandler
, NULL
);
2239 image
= XGetImage(gdi_display
, xpm
, 0, 0, image_w
, image_h
, AllPlanes
,
2241 X11DRV_check_error();
2242 XFreePixmap(gdi_display
, xpm
);
2244 if(!image
) goto no_image
;
2246 image
->red_mask
= visual
->red_mask
;
2247 image
->green_mask
= visual
->green_mask
;
2248 image
->blue_mask
= visual
->blue_mask
;
2250 for(idx
= 0; idx
< count
; idx
++) {
2251 SmoothGlyphGray(image
,
2252 offset
.x
+ image_off_x
- extents
.left
,
2253 offset
.y
+ image_off_y
- extents
.top
,
2254 formatEntry
->bitmaps
[wstr
[idx
]],
2255 &formatEntry
->gis
[wstr
[idx
]],
2256 physdev
->x11dev
->textPixel
);
2261 offset
.x
+= lpDx
[idx
* 2];
2262 offset
.y
+= lpDx
[idx
* 2 + 1];
2265 offset
.x
+= lpDx
[idx
];
2269 offset
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2270 offset
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2273 XPutImage(gdi_display
, physdev
->x11dev
->drawable
, physdev
->x11dev
->gc
, image
, 0, 0,
2274 image_x
, image_y
, image_w
, image_h
);
2275 XDestroyImage(image
);
2278 wine_tsx11_unlock();
2279 restore_clipping_region( physdev
->x11dev
, saved_region
);
2281 LeaveCriticalSection(&xrender_cs
);
2285 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2289 /* multiply the alpha channel of a picture */
2290 static void multiply_alpha( Picture pict
, XRenderPictFormat
*format
, int alpha
,
2291 int x
, int y
, int width
, int height
)
2293 XRenderPictureAttributes pa
;
2294 Pixmap src_pixmap
, mask_pixmap
;
2295 Picture src_pict
, mask_pict
;
2299 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
2300 mask_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
2301 pa
.repeat
= RepeatNormal
;
2302 src_pict
= pXRenderCreatePicture( gdi_display
, src_pixmap
, format
, CPRepeat
, &pa
);
2303 pa
.component_alpha
= True
;
2304 mask_pict
= pXRenderCreatePicture( gdi_display
, mask_pixmap
, format
, CPRepeat
|CPComponentAlpha
, &pa
);
2305 color
.red
= color
.green
= color
.blue
= color
.alpha
= 0xffff;
2306 pXRenderFillRectangle( gdi_display
, PictOpSrc
, src_pict
, &color
, 0, 0, 1, 1 );
2307 color
.alpha
= alpha
;
2308 pXRenderFillRectangle( gdi_display
, PictOpSrc
, mask_pict
, &color
, 0, 0, 1, 1 );
2309 pXRenderComposite( gdi_display
, PictOpInReverse
, src_pict
, mask_pict
, pict
,
2310 0, 0, 0, 0, x
, y
, width
, height
);
2311 pXRenderFreePicture( gdi_display
, src_pict
);
2312 pXRenderFreePicture( gdi_display
, mask_pict
);
2313 XFreePixmap( gdi_display
, src_pixmap
);
2314 XFreePixmap( gdi_display
, mask_pixmap
);
2315 wine_tsx11_unlock();
2318 /* Helper function for (stretched) blitting using xrender */
2319 static void xrender_blit( int op
, Picture src_pict
, Picture mask_pict
, Picture dst_pict
,
2320 int x_src
, int y_src
, int x_dst
, int y_dst
,
2321 double xscale
, double yscale
, int width
, int height
)
2323 int x_offset
, y_offset
;
2325 /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2326 * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2327 * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2329 if(xscale
!= 1.0 || yscale
!= 1.0)
2331 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2332 * in the wrong quadrant of the x-y plane.
2334 x_offset
= (xscale
< 0) ? -width
: 0;
2335 y_offset
= (yscale
< 0) ? -height
: 0;
2336 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
2342 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
2344 pXRenderComposite( gdi_display
, op
, src_pict
, mask_pict
, dst_pict
,
2345 x_offset
, y_offset
, 0, 0, x_dst
, y_dst
, width
, height
);
2346 wine_tsx11_unlock();
2349 /* Helper function for (stretched) mono->color blitting using xrender */
2350 static void xrender_mono_blit( Picture src_pict
, Picture dst_pict
,
2351 enum wxr_format dst_format
, XRenderColor
*fg
, XRenderColor
*bg
,
2352 int x_src
, int y_src
, int x_dst
, int y_dst
,
2353 double xscale
, double yscale
, int width
, int height
)
2356 int x_offset
, y_offset
;
2359 /* When doing a mono->color blit, the source data is used as mask, and the source picture
2360 * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
2363 EnterCriticalSection( &xrender_cs
);
2365 color
.alpha
= 0xffff; /* tile pict needs 100% alpha */
2366 tile_pict
= get_tile_pict( dst_format
, &color
);
2369 pXRenderFillRectangle( gdi_display
, PictOpSrc
, dst_pict
, fg
, x_dst
, y_dst
, width
, height
);
2371 if (xscale
!= 1.0 || yscale
!= 1.0)
2373 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2374 * in the wrong quadrant of the x-y plane.
2376 x_offset
= (xscale
< 0) ? -width
: 0;
2377 y_offset
= (yscale
< 0) ? -height
: 0;
2378 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
2384 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
2386 pXRenderComposite(gdi_display
, PictOpOver
, tile_pict
, src_pict
, dst_pict
,
2387 0, 0, x_offset
, y_offset
, x_dst
, y_dst
, width
, height
);
2388 wine_tsx11_unlock();
2389 LeaveCriticalSection( &xrender_cs
);
2391 /* force the alpha channel for background pixels, it has been set to 100% by the tile */
2392 if (bg
->alpha
!= 0xffff && (dst_format
== WXR_FORMAT_A8R8G8B8
|| dst_format
== WXR_FORMAT_B8G8R8A8
))
2393 multiply_alpha( dst_pict
, pict_formats
[dst_format
], bg
->alpha
, x_dst
, y_dst
, width
, height
);
2396 /* create a pixmap and render picture for an image */
2397 static DWORD
create_image_pixmap( BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2398 struct bitblt_coords
*src
, enum wxr_format format
,
2399 Pixmap
*pixmap
, Picture
*pict
, BOOL
*use_repeat
)
2402 int width
= src
->visrect
.right
- src
->visrect
.left
;
2403 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2404 int depth
= pict_formats
[format
]->depth
;
2405 struct gdi_image_bits dst_bits
;
2406 XRenderPictureAttributes pa
;
2410 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
2411 info
->bmiHeader
.biWidth
, height
, 32, 0 );
2412 wine_tsx11_unlock();
2413 if (!image
) return ERROR_OUTOFMEMORY
;
2415 ret
= copy_image_bits( info
, (format
== WXR_FORMAT_R8G8B8
), image
, bits
, &dst_bits
, src
, NULL
, ~0u );
2416 if (ret
) return ret
;
2418 image
->data
= dst_bits
.ptr
;
2419 /* hack: make sure the bits are readable if we are reading from a DIB section */
2420 /* to be removed once we get rid of DIB access protections */
2421 if (!dst_bits
.is_copy
) IsBadReadPtr( dst_bits
.ptr
, image
->height
* image
->bytes_per_line
);
2423 *use_repeat
= (width
== 1 && height
== 1);
2424 pa
.repeat
= *use_repeat
? RepeatNormal
: RepeatNone
;
2427 *pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
2428 XPutImage( gdi_display
, *pixmap
, get_bitmap_gc( depth
), image
,
2429 src
->visrect
.left
, 0, 0, 0, width
, height
);
2430 *pict
= pXRenderCreatePicture( gdi_display
, *pixmap
, pict_formats
[format
], CPRepeat
, &pa
);
2431 wine_tsx11_unlock();
2433 /* make coordinates relative to the pixmap */
2434 src
->x
-= src
->visrect
.left
;
2435 src
->y
-= src
->visrect
.top
;
2436 OffsetRect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
2440 XDestroyImage( image
);
2441 wine_tsx11_unlock();
2442 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
2446 static void xrender_stretch_blit( struct xrender_physdev
*physdev_src
, struct xrender_physdev
*physdev_dst
,
2447 Drawable drawable
, const struct bitblt_coords
*src
,
2448 const struct bitblt_coords
*dst
)
2450 int width
= abs( dst
->width
);
2451 int height
= abs( dst
->height
);
2452 int x_src
= physdev_src
->x11dev
->dc_rect
.left
+ src
->x
;
2453 int y_src
= physdev_src
->x11dev
->dc_rect
.top
+ src
->y
;
2455 Picture src_pict
= 0, dst_pict
, mask_pict
= 0;
2457 double xscale
, yscale
;
2459 use_repeat
= use_source_repeat( physdev_src
);
2462 xscale
= src
->width
/ (double)dst
->width
;
2463 yscale
= src
->height
/ (double)dst
->height
;
2465 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2467 if (drawable
) /* using an intermediate pixmap */
2469 XRenderPictureAttributes pa
;
2473 pa
.repeat
= RepeatNone
;
2475 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, physdev_dst
->pict_format
, CPRepeat
, &pa
);
2476 wine_tsx11_unlock();
2480 x_dst
= physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
;
2481 y_dst
= physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
;
2482 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2485 if (src
->width
< 0) x_src
+= src
->width
+ 1;
2486 if (src
->height
< 0) y_src
+= src
->height
+ 1;
2487 if (dst
->width
< 0) x_dst
+= dst
->width
+ 1;
2488 if (dst
->height
< 0) y_dst
+= dst
->height
+ 1;
2490 src_pict
= get_xrender_picture_source( physdev_src
, use_repeat
);
2493 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2495 XRenderColor fg
, bg
;
2497 get_xrender_color( physdev_dst
->pict_format
, physdev_dst
->x11dev
->textPixel
, &fg
);
2498 get_xrender_color( physdev_dst
->pict_format
, physdev_dst
->x11dev
->backgroundPixel
, &bg
);
2499 fg
.alpha
= bg
.alpha
= 0;
2501 xrender_mono_blit( src_pict
, dst_pict
, physdev_dst
->format
, &fg
, &bg
,
2502 x_src
, y_src
, x_dst
, y_dst
, xscale
, yscale
, width
, height
);
2504 else /* color -> color (can be at different depths) or mono -> mono */
2506 if (physdev_dst
->x11dev
->depth
== 32 && physdev_src
->x11dev
->depth
< 32)
2507 mask_pict
= get_no_alpha_mask();
2509 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
,
2510 x_src
, y_src
, x_dst
, y_dst
, xscale
, yscale
, width
, height
);
2516 pXRenderFreePicture( gdi_display
, dst_pict
);
2517 wine_tsx11_unlock();
2522 static void xrender_put_image( Pixmap src_pixmap
, Picture src_pict
, Picture mask_pict
, HRGN clip
,
2523 XRenderPictFormat
*dst_format
, struct xrender_physdev
*physdev
,
2524 Drawable drawable
, struct bitblt_coords
*src
,
2525 struct bitblt_coords
*dst
, BOOL use_repeat
)
2527 int x_src
, y_src
, x_dst
, y_dst
;
2529 XRenderPictureAttributes pa
;
2530 double xscale
, yscale
;
2532 if (drawable
) /* using an intermediate pixmap */
2534 RGNDATA
*clip_data
= NULL
;
2536 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
2539 pa
.repeat
= RepeatNone
;
2541 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, dst_format
, CPRepeat
, &pa
);
2543 pXRenderSetPictureClipRectangles( gdi_display
, dst_pict
, 0, 0,
2544 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
2545 wine_tsx11_unlock();
2546 HeapFree( GetProcessHeap(), 0, clip_data
);
2550 x_dst
= physdev
->x11dev
->dc_rect
.left
+ dst
->x
;
2551 y_dst
= physdev
->x11dev
->dc_rect
.top
+ dst
->y
;
2552 dst_pict
= get_xrender_picture( physdev
, clip
, &dst
->visrect
);
2557 xscale
= src
->width
/ (double)dst
->width
;
2558 yscale
= src
->height
/ (double)dst
->height
;
2560 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2564 if (src
->width
< 0) x_src
+= src
->width
+ 1;
2565 if (src
->height
< 0) y_src
+= src
->height
+ 1;
2566 if (dst
->width
< 0) x_dst
+= dst
->width
+ 1;
2567 if (dst
->height
< 0) y_dst
+= dst
->height
+ 1;
2569 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
, x_src
, y_src
, x_dst
, y_dst
,
2570 xscale
, yscale
, abs( dst
->width
), abs( dst
->height
));
2575 pXRenderFreePicture( gdi_display
, dst_pict
);
2576 wine_tsx11_unlock();
2581 /***********************************************************************
2582 * xrenderdrv_StretchBlt
2584 static BOOL
xrenderdrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2585 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
2587 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2588 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2589 BOOL stretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
2591 if (src_dev
->funcs
!= dst_dev
->funcs
)
2593 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
2594 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
2597 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2599 /* XRender is of no use for color -> mono */
2600 if (physdev_dst
->format
== WXR_FORMAT_MONO
&& physdev_src
->format
!= WXR_FORMAT_MONO
)
2601 goto x11drv_fallback
;
2603 /* if not stretching, we only need to handle format conversion */
2604 if (!stretch
&& physdev_dst
->format
== physdev_src
->format
) goto x11drv_fallback
;
2606 X11DRV_LockDIBSection( physdev_dst
->x11dev
, DIB_Status_GdiMod
);
2607 if (physdev_dst
!= physdev_src
) X11DRV_LockDIBSection( physdev_src
->x11dev
, DIB_Status_GdiMod
);
2613 struct bitblt_coords tmp
;
2615 /* make coordinates relative to tmp pixmap */
2617 tmp
.x
-= tmp
.visrect
.left
;
2618 tmp
.y
-= tmp
.visrect
.top
;
2619 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2622 tmpGC
= XCreateGC( gdi_display
, physdev_dst
->x11dev
->drawable
, 0, NULL
);
2623 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
2624 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
2625 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2626 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev_dst
->x11dev
->depth
);
2627 wine_tsx11_unlock();
2629 xrender_stretch_blit( physdev_src
, physdev_dst
, tmp_pixmap
, src
, &tmp
);
2630 execute_rop( physdev_dst
->x11dev
, tmp_pixmap
, tmpGC
, &dst
->visrect
, rop
);
2633 XFreePixmap( gdi_display
, tmp_pixmap
);
2634 XFreeGC( gdi_display
, tmpGC
);
2635 wine_tsx11_unlock();
2637 else xrender_stretch_blit( physdev_src
, physdev_dst
, 0, src
, dst
);
2639 if (physdev_dst
!= physdev_src
) X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2640 X11DRV_UnlockDIBSection( physdev_dst
->x11dev
, TRUE
);
2644 return X11DRV_StretchBlt( &physdev_dst
->x11dev
->dev
, dst
, &physdev_src
->x11dev
->dev
, src
, rop
);
2648 /***********************************************************************
2649 * xrenderdrv_PutImage
2651 static DWORD
xrenderdrv_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
2652 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
2653 struct bitblt_coords
*dst
, DWORD rop
)
2655 struct xrender_physdev
*physdev
;
2656 X_PHYSBITMAP
*bitmap
;
2660 enum wxr_format src_format
, dst_format
;
2661 XRenderPictFormat
*pict_format
;
2663 Picture src_pict
, mask_pict
= 0;
2666 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2670 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
2672 dst_format
= get_xrender_format_from_color_shifts( bitmap
->depth
, &bitmap
->color_shifts
);
2676 physdev
= get_xrender_dev( dev
);
2678 dst_format
= physdev
->format
;
2681 src_format
= get_xrender_format_from_bitmapinfo( info
, TRUE
);
2682 if (!(pict_format
= pict_formats
[src_format
])) goto update_format
;
2684 /* make sure we can create an image with the same bpp */
2685 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2688 /* mono <-> color conversions not supported */
2689 if ((src_format
!= dst_format
) && (src_format
== WXR_FORMAT_MONO
|| dst_format
== WXR_FORMAT_MONO
))
2690 goto x11drv_fallback
;
2692 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2694 if (!has_alpha( src_format
) && has_alpha( dst_format
)) mask_pict
= get_no_alpha_mask();
2696 ret
= create_image_pixmap( info
, bits
, src
, src_format
, &src_pixmap
, &src_pict
, &use_repeat
);
2699 struct bitblt_coords tmp
;
2703 HRGN rgn
= CreateRectRgnIndirect( &dst
->visrect
);
2704 if (clip
) CombineRgn( rgn
, rgn
, clip
, RGN_AND
);
2706 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
2708 xrender_put_image( src_pixmap
, src_pict
, mask_pict
, rgn
,
2709 pict_formats
[dst_format
], NULL
, bitmap
->pixmap
, src
, dst
, use_repeat
);
2711 X11DRV_DIB_Unlock( bitmap
, TRUE
);
2712 DeleteObject( rgn
);
2716 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
2720 RGNDATA
*clip_data
= NULL
;
2722 /* make coordinates relative to tmp pixmap */
2724 tmp
.x
-= tmp
.visrect
.left
;
2725 tmp
.y
-= tmp
.visrect
.top
;
2726 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2728 if (clip
) clip_data
= add_extra_clipping_region( physdev
->x11dev
, clip
);
2731 gc
= XCreateGC( gdi_display
, physdev
->x11dev
->drawable
, 0, NULL
);
2732 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
2733 XSetGraphicsExposures( gdi_display
, gc
, False
);
2734 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2735 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev
->x11dev
->depth
);
2736 wine_tsx11_unlock();
2738 xrender_put_image( src_pixmap
, src_pict
, mask_pict
, NULL
, physdev
->pict_format
,
2739 NULL
, tmp_pixmap
, src
, &tmp
, use_repeat
);
2740 execute_rop( physdev
->x11dev
, tmp_pixmap
, gc
, &dst
->visrect
, rop
);
2743 XFreePixmap( gdi_display
, tmp_pixmap
);
2744 XFreeGC( gdi_display
, gc
);
2745 wine_tsx11_unlock();
2747 restore_clipping_region( physdev
->x11dev
, clip_data
);
2749 else xrender_put_image( src_pixmap
, src_pict
, mask_pict
, clip
,
2750 physdev
->pict_format
, physdev
, 0, src
, dst
, use_repeat
);
2752 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2756 pXRenderFreePicture( gdi_display
, src_pict
);
2757 XFreePixmap( gdi_display
, src_pixmap
);
2758 wine_tsx11_unlock();
2763 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2764 set_color_info( pict_formats
[dst_format
], info
);
2765 return ERROR_BAD_FORMAT
;
2768 if (hbitmap
) return X11DRV_PutImage( dev
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
2769 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
2770 return dev
->funcs
->pPutImage( dev
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
2774 /***********************************************************************
2775 * xrenderdrv_BlendImage
2777 static DWORD
xrenderdrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2778 struct bitblt_coords
*src
, struct bitblt_coords
*dst
,
2779 BLENDFUNCTION func
)
2781 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2783 enum wxr_format format
;
2784 XRenderPictFormat
*pict_format
;
2785 Picture dst_pict
, src_pict
, mask_pict
;
2789 if (!X11DRV_XRender_Installed
)
2791 dev
= GET_NEXT_PHYSDEV( dev
, pBlendImage
);
2792 return dev
->funcs
->pBlendImage( dev
, info
, bits
, src
, dst
, func
);
2795 format
= get_xrender_format_from_bitmapinfo( info
, func
.AlphaFormat
& AC_SRC_ALPHA
);
2796 if (!(pict_format
= pict_formats
[format
])) goto update_format
;
2798 /* make sure we can create an image with the same bpp */
2799 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2802 if (format
== WXR_FORMAT_MONO
&& physdev
->format
!= WXR_FORMAT_MONO
)
2805 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2807 ret
= create_image_pixmap( info
, bits
, src
, format
, &src_pixmap
, &src_pict
, &use_repeat
);
2810 double xscale
, yscale
;
2812 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
2816 xscale
= src
->width
/ (double)dst
->width
;
2817 yscale
= src
->height
/ (double)dst
->height
;
2819 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2821 dst_pict
= get_xrender_picture( physdev
, 0, &dst
->visrect
);
2823 EnterCriticalSection( &xrender_cs
);
2824 mask_pict
= get_mask_pict( func
.SourceConstantAlpha
* 257 );
2826 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
, src
->x
, src
->y
,
2827 physdev
->x11dev
->dc_rect
.left
+ dst
->x
,
2828 physdev
->x11dev
->dc_rect
.top
+ dst
->y
,
2829 xscale
, yscale
, dst
->width
, dst
->height
);
2832 pXRenderFreePicture( gdi_display
, src_pict
);
2833 XFreePixmap( gdi_display
, src_pixmap
);
2834 wine_tsx11_unlock();
2836 LeaveCriticalSection( &xrender_cs
);
2838 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2843 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2844 set_color_info( physdev
->pict_format
, info
);
2845 return ERROR_BAD_FORMAT
;
2849 /***********************************************************************
2850 * xrenderdrv_AlphaBlend
2852 static BOOL
xrenderdrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2853 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION blendfn
)
2855 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2856 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2857 Picture dst_pict
, src_pict
= 0, mask_pict
= 0, tmp_pict
= 0;
2858 XRenderPictureAttributes pa
;
2859 Pixmap tmp_pixmap
= 0;
2860 double xscale
, yscale
;
2863 if (!X11DRV_XRender_Installed
|| src_dev
->funcs
!= dst_dev
->funcs
)
2865 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
2866 return dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, blendfn
);
2869 if (physdev_dst
!= physdev_src
)
2871 int status
= X11DRV_LockDIBSection( physdev_src
->x11dev
, DIB_Status_None
);
2872 if (status
== DIB_Status_AppMod
|| status
== DIB_Status_InSync
)
2874 X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2875 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
2876 return dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, blendfn
);
2878 X11DRV_CoerceDIBSection( physdev_src
->x11dev
, DIB_Status_GdiMod
);
2880 X11DRV_LockDIBSection( physdev_dst
->x11dev
, DIB_Status_GdiMod
);
2882 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2884 use_repeat
= use_source_repeat( physdev_src
);
2887 xscale
= src
->width
/ (double)dst
->width
;
2888 yscale
= src
->height
/ (double)dst
->height
;
2890 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2892 src_pict
= get_xrender_picture_source( physdev_src
, use_repeat
);
2894 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2896 /* mono -> color blending needs an intermediate color pixmap */
2897 XRenderColor fg
, bg
;
2898 int width
= src
->visrect
.right
- src
->visrect
.left
;
2899 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2901 /* blending doesn't use the destination DC colors */
2902 fg
.red
= fg
.green
= fg
.blue
= 0;
2903 bg
.red
= bg
.green
= bg
.blue
= 0xffff;
2904 fg
.alpha
= bg
.alpha
= 0xffff;
2907 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
,
2908 physdev_dst
->pict_format
->depth
);
2909 pa
.repeat
= use_repeat
? RepeatNormal
: RepeatNone
;
2910 tmp_pict
= pXRenderCreatePicture( gdi_display
, tmp_pixmap
, physdev_dst
->pict_format
,
2912 wine_tsx11_unlock();
2914 xrender_mono_blit( src_pict
, tmp_pict
, physdev_dst
->format
, &fg
, &bg
,
2915 src
->visrect
.left
, src
->visrect
.top
, 0, 0, 1, 1, width
, height
);
2917 else if (!(blendfn
.AlphaFormat
& AC_SRC_ALPHA
) && physdev_src
->pict_format
)
2919 /* we need a source picture with no alpha */
2920 enum wxr_format format
= get_format_without_alpha( physdev_src
->format
);
2921 if (format
!= physdev_src
->format
)
2924 pa
.subwindow_mode
= IncludeInferiors
;
2925 pa
.repeat
= use_repeat
? RepeatNormal
: RepeatNone
;
2926 tmp_pict
= pXRenderCreatePicture( gdi_display
, physdev_src
->x11dev
->drawable
,
2927 pict_formats
[format
], CPSubwindowMode
|CPRepeat
, &pa
);
2928 wine_tsx11_unlock();
2932 if (tmp_pict
) src_pict
= tmp_pict
;
2934 EnterCriticalSection( &xrender_cs
);
2935 mask_pict
= get_mask_pict( blendfn
.SourceConstantAlpha
* 257 );
2937 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
,
2938 physdev_src
->x11dev
->dc_rect
.left
+ src
->x
,
2939 physdev_src
->x11dev
->dc_rect
.top
+ src
->y
,
2940 physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
,
2941 physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
,
2942 xscale
, yscale
, dst
->width
, dst
->height
);
2945 if (tmp_pict
) pXRenderFreePicture( gdi_display
, tmp_pict
);
2946 if (tmp_pixmap
) XFreePixmap( gdi_display
, tmp_pixmap
);
2947 wine_tsx11_unlock();
2949 LeaveCriticalSection( &xrender_cs
);
2950 if (physdev_src
!= physdev_dst
) X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2951 X11DRV_UnlockDIBSection( physdev_dst
->x11dev
, TRUE
);
2956 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE
*physDev
, X_PHYSBITMAP
*physBitmap
, int width
, int height
)
2958 /* At depths >1, the depth of physBitmap and physDev might not be the same e.g. the physbitmap might be a 16-bit DIB while the physdev uses 24-bit */
2959 int depth
= physBitmap
->depth
== 1 ? 1 : physDev
->depth
;
2960 enum wxr_format src_format
= get_xrender_format_from_color_shifts(physBitmap
->depth
, &physBitmap
->color_shifts
);
2961 enum wxr_format dst_format
= get_xrender_format_from_color_shifts(physDev
->depth
, physDev
->color_shifts
);
2964 physDev
->brush
.pixmap
= XCreatePixmap(gdi_display
, root_window
, width
, height
, depth
);
2966 /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2967 if( (physBitmap
->depth
== 1) || (!X11DRV_XRender_Installed
&& physDev
->depth
== physBitmap
->depth
) ||
2968 (src_format
== dst_format
) )
2970 XCopyArea( gdi_display
, physBitmap
->pixmap
, physDev
->brush
.pixmap
,
2971 get_bitmap_gc(physBitmap
->depth
), 0, 0, width
, height
, 0, 0 );
2973 else /* We need depth conversion */
2975 Picture src_pict
, dst_pict
;
2976 XRenderPictureAttributes pa
;
2977 pa
.subwindow_mode
= IncludeInferiors
;
2978 pa
.repeat
= RepeatNone
;
2980 src_pict
= pXRenderCreatePicture(gdi_display
, physBitmap
->pixmap
,
2981 pict_formats
[src_format
], CPSubwindowMode
|CPRepeat
, &pa
);
2982 dst_pict
= pXRenderCreatePicture(gdi_display
, physDev
->brush
.pixmap
,
2983 pict_formats
[dst_format
], CPSubwindowMode
|CPRepeat
, &pa
);
2985 xrender_blit(PictOpSrc
, src_pict
, 0, dst_pict
, 0, 0, 0, 0, 1.0, 1.0, width
, height
);
2986 pXRenderFreePicture(gdi_display
, src_pict
);
2987 pXRenderFreePicture(gdi_display
, dst_pict
);
2989 wine_tsx11_unlock();
2992 static const struct gdi_dc_funcs xrender_funcs
=
2994 NULL
, /* pAbortDoc */
2995 NULL
, /* pAbortPath */
2996 xrenderdrv_AlphaBlend
, /* pAlphaBlend */
2997 NULL
, /* pAngleArc */
3000 NULL
, /* pBeginPath */
3001 xrenderdrv_BlendImage
, /* pBlendImage */
3002 NULL
, /* pChoosePixelFormat */
3004 NULL
, /* pCloseFigure */
3005 xrenderdrv_CreateBitmap
, /* pCreateBitmap */
3006 xrenderdrv_CreateCompatibleDC
, /* pCreateCompatibleDC */
3007 xrenderdrv_CreateDC
, /* pCreateDC */
3008 NULL
, /* pCreateDIBSection */
3009 xrenderdrv_DeleteBitmap
, /* pDeleteBitmap */
3010 xrenderdrv_DeleteDC
, /* pDeleteDC */
3011 NULL
, /* pDeleteObject */
3012 NULL
, /* pDescribePixelFormat */
3013 NULL
, /* pDeviceCapabilities */
3014 NULL
, /* pEllipse */
3016 NULL
, /* pEndPage */
3017 NULL
, /* pEndPath */
3018 NULL
, /* pEnumDeviceFonts */
3019 NULL
, /* pEnumICMProfiles */
3020 NULL
, /* pExcludeClipRect */
3021 NULL
, /* pExtDeviceMode */
3022 xrenderdrv_ExtEscape
, /* pExtEscape */
3023 NULL
, /* pExtFloodFill */
3024 NULL
, /* pExtSelectClipRgn */
3025 xrenderdrv_ExtTextOut
, /* pExtTextOut */
3026 NULL
, /* pFillPath */
3027 NULL
, /* pFillRgn */
3028 NULL
, /* pFlattenPath */
3029 NULL
, /* pFrameRgn */
3030 NULL
, /* pGdiComment */
3031 NULL
, /* pGetCharWidth */
3032 NULL
, /* pGetDeviceCaps */
3033 NULL
, /* pGetDeviceGammaRamp */
3034 NULL
, /* pGetICMProfile */
3035 xrenderdrv_GetImage
, /* pGetImage */
3036 NULL
, /* pGetNearestColor */
3037 NULL
, /* pGetPixel */
3038 NULL
, /* pGetPixelFormat */
3039 NULL
, /* pGetSystemPaletteEntries */
3040 NULL
, /* pGetTextExtentExPoint */
3041 NULL
, /* pGetTextMetrics */
3042 NULL
, /* pIntersectClipRect */
3043 NULL
, /* pInvertRgn */
3045 NULL
, /* pModifyWorldTransform */
3047 NULL
, /* pOffsetClipRgn */
3048 NULL
, /* pOffsetViewportOrg */
3049 NULL
, /* pOffsetWindowOrg */
3050 NULL
, /* pPaintRgn */
3053 NULL
, /* pPolyBezier */
3054 NULL
, /* pPolyBezierTo */
3055 NULL
, /* pPolyDraw */
3056 NULL
, /* pPolyPolygon */
3057 NULL
, /* pPolyPolyline */
3058 NULL
, /* pPolygon */
3059 NULL
, /* pPolyline */
3060 NULL
, /* pPolylineTo */
3061 xrenderdrv_PutImage
, /* pPutImage */
3062 NULL
, /* pRealizeDefaultPalette */
3063 NULL
, /* pRealizePalette */
3064 NULL
, /* pRectangle */
3065 NULL
, /* pResetDC */
3066 NULL
, /* pRestoreDC */
3067 NULL
, /* pRoundRect */
3069 NULL
, /* pScaleViewportExt */
3070 NULL
, /* pScaleWindowExt */
3071 xrenderdrv_SelectBitmap
, /* pSelectBitmap */
3072 NULL
, /* pSelectBrush */
3073 NULL
, /* pSelectClipPath */
3074 xrenderdrv_SelectFont
, /* pSelectFont */
3075 NULL
, /* pSelectPalette */
3076 NULL
, /* pSelectPen */
3077 NULL
, /* pSetArcDirection */
3078 NULL
, /* pSetBkColor */
3079 NULL
, /* pSetBkMode */
3080 NULL
, /* pSetDCBrushColor */
3081 NULL
, /* pSetDCPenColor */
3082 NULL
, /* pSetDIBColorTable */
3083 NULL
, /* pSetDIBitsToDevice */
3084 xrenderdrv_SetDeviceClipping
, /* pSetDeviceClipping */
3085 NULL
, /* pSetDeviceGammaRamp */
3086 NULL
, /* pSetLayout */
3087 NULL
, /* pSetMapMode */
3088 NULL
, /* pSetMapperFlags */
3089 NULL
, /* pSetPixel */
3090 NULL
, /* pSetPixelFormat */
3091 NULL
, /* pSetPolyFillMode */
3092 NULL
, /* pSetROP2 */
3093 NULL
, /* pSetRelAbs */
3094 NULL
, /* pSetStretchBltMode */
3095 NULL
, /* pSetTextAlign */
3096 NULL
, /* pSetTextCharacterExtra */
3097 NULL
, /* pSetTextColor */
3098 NULL
, /* pSetTextJustification */
3099 NULL
, /* pSetViewportExt */
3100 NULL
, /* pSetViewportOrg */
3101 NULL
, /* pSetWindowExt */
3102 NULL
, /* pSetWindowOrg */
3103 NULL
, /* pSetWorldTransform */
3104 NULL
, /* pStartDoc */
3105 NULL
, /* pStartPage */
3106 xrenderdrv_StretchBlt
, /* pStretchBlt */
3107 NULL
, /* pStretchDIBits */
3108 NULL
, /* pStrokeAndFillPath */
3109 NULL
, /* pStrokePath */
3110 NULL
, /* pSwapBuffers */
3111 NULL
, /* pUnrealizePalette */
3112 NULL
, /* pWidenPath */
3113 /* OpenGL not supported */
3116 #else /* SONAME_LIBXRENDER */
3118 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
3120 TRACE("XRender support not compiled in.\n");
3124 void X11DRV_XRender_Finalize(void)
3128 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE
*physDev
, X_PHYSBITMAP
*physBitmap
, int width
, int height
)
3131 physDev
->brush
.pixmap
= XCreatePixmap(gdi_display
, root_window
, width
, height
, physBitmap
->pixmap_depth
);
3133 XCopyArea( gdi_display
, physBitmap
->pixmap
, physDev
->brush
.pixmap
,
3134 get_bitmap_gc(physBitmap
->pixmap_depth
), 0, 0, width
, height
, 0, 0 );
3135 wine_tsx11_unlock();
3138 BOOL
X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP
*physBitmap
, int bits_pixel
, const DIBSECTION
*dib
)
3143 #endif /* SONAME_LIBXRENDER */