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 enum wxr_format
get_format_without_alpha( enum wxr_format format
)
256 case WXR_FORMAT_A8R8G8B8
: return WXR_FORMAT_X8R8G8B8
;
257 case WXR_FORMAT_B8G8R8A8
: return WXR_FORMAT_B8G8R8X8
;
258 default: return format
;
262 static BOOL
get_xrender_template(const WineXRenderFormatTemplate
*fmt
, XRenderPictFormat
*templ
, unsigned long *mask
)
265 templ
->type
= PictTypeDirect
;
266 templ
->depth
= fmt
->depth
;
267 templ
->direct
.alpha
= fmt
->alpha
;
268 templ
->direct
.alphaMask
= fmt
->alphaMask
;
269 templ
->direct
.red
= fmt
->red
;
270 templ
->direct
.redMask
= fmt
->redMask
;
271 templ
->direct
.green
= fmt
->green
;
272 templ
->direct
.greenMask
= fmt
->greenMask
;
273 templ
->direct
.blue
= fmt
->blue
;
274 templ
->direct
.blueMask
= fmt
->blueMask
;
277 *mask
= PictFormatType
| PictFormatDepth
| PictFormatAlpha
| PictFormatAlphaMask
| PictFormatRed
| PictFormatRedMask
| PictFormatGreen
| PictFormatGreenMask
| PictFormatBlue
| PictFormatBlueMask
;
282 static BOOL
is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate
*fmt
)
284 if(fmt
->depth
!= screen_depth
)
286 if( (fmt
->redMask
<< fmt
->red
) != visual
->red_mask
)
288 if( (fmt
->greenMask
<< fmt
->green
) != visual
->green_mask
)
290 if( (fmt
->blueMask
<< fmt
->blue
) != visual
->blue_mask
)
293 /* We never select a default ARGB visual */
300 static int load_xrender_formats(void)
305 for (i
= 0; i
< WXR_NB_FORMATS
; i
++)
307 XRenderPictFormat templ
;
309 if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template
[i
]))
312 pict_formats
[i
] = pXRenderFindVisualFormat(gdi_display
, visual
);
313 if (!pict_formats
[i
])
315 /* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
316 if (visual
->class == DirectColor
)
319 if (XMatchVisualInfo( gdi_display
, DefaultScreen(gdi_display
),
320 screen_depth
, TrueColor
, &info
))
322 pict_formats
[i
] = pXRenderFindVisualFormat(gdi_display
, info
.visual
);
323 if (pict_formats
[i
]) visual
= info
.visual
;
328 if (pict_formats
[i
]) default_format
= i
;
332 unsigned long mask
= 0;
333 get_xrender_template(&wxr_formats_template
[i
], &templ
, &mask
);
336 pict_formats
[i
] = pXRenderFindFormat(gdi_display
, mask
, &templ
, 0);
342 TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_formats
[i
]->id
, i
);
348 /***********************************************************************
349 * X11DRV_XRender_Init
351 * Let's see if our XServer has the extension available
354 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
358 if (client_side_with_render
&&
359 (xrender_handle
= wine_dlopen(SONAME_LIBXRENDER
, RTLD_NOW
, NULL
, 0)))
362 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
363 LOAD_FUNCPTR(XRenderAddGlyphs
)
364 LOAD_FUNCPTR(XRenderComposite
)
365 LOAD_FUNCPTR(XRenderCompositeText16
)
366 LOAD_FUNCPTR(XRenderCreateGlyphSet
)
367 LOAD_FUNCPTR(XRenderCreatePicture
)
368 LOAD_FUNCPTR(XRenderFillRectangle
)
369 LOAD_FUNCPTR(XRenderFindFormat
)
370 LOAD_FUNCPTR(XRenderFindVisualFormat
)
371 LOAD_FUNCPTR(XRenderFreeGlyphSet
)
372 LOAD_FUNCPTR(XRenderFreePicture
)
373 LOAD_FUNCPTR(XRenderSetPictureClipRectangles
)
374 LOAD_FUNCPTR(XRenderQueryExtension
)
376 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
377 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = wine_dlsym(xrender_handle, #f, NULL, 0);
378 LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform
)
379 #undef LOAD_OPTIONAL_FUNCPTR
383 X11DRV_XRender_Installed
= pXRenderQueryExtension(gdi_display
, &event_base
, &xrender_error_base
);
385 if(X11DRV_XRender_Installed
) {
386 TRACE("Xrender is up and running error_base = %d\n", xrender_error_base
);
387 if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
391 "Wine has detected that you probably have a buggy version\n"
392 "of libXrender.so . Because of this client side font rendering\n"
393 "will be disabled. Please upgrade this library.\n");
394 X11DRV_XRender_Installed
= FALSE
;
398 if (!visual
->red_mask
|| !visual
->green_mask
|| !visual
->blue_mask
) {
399 WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
400 X11DRV_XRender_Installed
= FALSE
;
405 #ifdef SONAME_LIBFONTCONFIG
406 if ((fontconfig_handle
= wine_dlopen(SONAME_LIBFONTCONFIG
, RTLD_NOW
, NULL
, 0)))
408 #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;}
409 LOAD_FUNCPTR(FcConfigSubstitute
);
410 LOAD_FUNCPTR(FcDefaultSubstitute
);
411 LOAD_FUNCPTR(FcFontMatch
);
412 LOAD_FUNCPTR(FcInit
);
413 LOAD_FUNCPTR(FcPatternCreate
);
414 LOAD_FUNCPTR(FcPatternDestroy
);
415 LOAD_FUNCPTR(FcPatternAddInteger
);
416 LOAD_FUNCPTR(FcPatternAddString
);
417 LOAD_FUNCPTR(FcPatternGetBool
);
418 LOAD_FUNCPTR(FcPatternGetInteger
);
419 LOAD_FUNCPTR(FcPatternGetString
);
421 fontconfig_installed
= pFcInit();
423 else TRACE( "cannot find the fontconfig library " SONAME_LIBFONTCONFIG
"\n" );
427 if(X11DRV_XRender_Installed
|| client_side_with_core
)
429 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
430 sizeof(*glyphsetCache
) * INIT_CACHE_SIZE
);
432 glyphsetCacheSize
= INIT_CACHE_SIZE
;
434 for(i
= 0; i
< INIT_CACHE_SIZE
; i
++) {
435 glyphsetCache
[i
].next
= i
+ 1;
436 glyphsetCache
[i
].count
= -1;
438 glyphsetCache
[i
-1].next
= -1;
439 using_client_side_fonts
= 1;
441 if(!X11DRV_XRender_Installed
) {
442 TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
443 if(screen_depth
<= 8 || !client_side_antialias_with_core
)
446 if(screen_depth
<= 8 || !client_side_antialias_with_render
)
449 return &xrender_funcs
;
451 TRACE("Using X11 core fonts\n");
455 /* Helper function to convert from a color packed in a 32-bit integer to a XRenderColor */
456 static void get_xrender_color( XRenderPictFormat
*pf
, int src_color
, XRenderColor
*dst_color
)
458 if(pf
->direct
.redMask
)
459 dst_color
->red
= ((src_color
>> pf
->direct
.red
) & pf
->direct
.redMask
) * 65535/pf
->direct
.redMask
;
463 if(pf
->direct
.greenMask
)
464 dst_color
->green
= ((src_color
>> pf
->direct
.green
) & pf
->direct
.greenMask
) * 65535/pf
->direct
.greenMask
;
466 dst_color
->green
= 0;
468 if(pf
->direct
.blueMask
)
469 dst_color
->blue
= ((src_color
>> pf
->direct
.blue
) & pf
->direct
.blueMask
) * 65535/pf
->direct
.blueMask
;
473 dst_color
->alpha
= 0xffff;
476 static enum wxr_format
get_xrender_format_from_color_shifts(int depth
, ColorShifts
*shifts
)
478 int redMask
, greenMask
, blueMask
;
481 if (depth
== 1) return WXR_FORMAT_MONO
;
483 /* physDevs of a depth <=8, don't have color_shifts set and XRender can't handle those except for 1-bit */
484 if (!shifts
) return default_format
;
486 redMask
= shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
;
487 greenMask
= shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
;
488 blueMask
= shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
;
490 /* Try to locate a format which matches the specification of the dibsection. */
491 for(i
= 0; i
< WXR_NB_FORMATS
; i
++)
493 if( depth
== wxr_formats_template
[i
].depth
&&
494 redMask
== (wxr_formats_template
[i
].redMask
<< wxr_formats_template
[i
].red
) &&
495 greenMask
== (wxr_formats_template
[i
].greenMask
<< wxr_formats_template
[i
].green
) &&
496 blueMask
== (wxr_formats_template
[i
].blueMask
<< wxr_formats_template
[i
].blue
) )
500 /* This should not happen because when we reach 'shifts' must have been set and we only allows shifts which are backed by X */
501 ERR("No XRender format found for %u %08x/%08x/%08x\n", depth
, redMask
, greenMask
, blueMask
);
502 return WXR_INVALID_FORMAT
;
505 static enum wxr_format
get_xrender_format_from_bitmapinfo( const BITMAPINFO
*info
, BOOL use_alpha
)
507 if (info
->bmiHeader
.biPlanes
!= 1) return WXR_INVALID_FORMAT
;
509 switch (info
->bmiHeader
.biBitCount
)
512 return WXR_FORMAT_MONO
;
517 if (info
->bmiHeader
.biCompression
!= BI_RGB
) break;
518 return WXR_FORMAT_R8G8B8
;
521 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
523 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
526 for (i
= 0; i
< WXR_NB_FORMATS
; i
++)
528 if (info
->bmiHeader
.biBitCount
== wxr_formats_template
[i
].depth
&&
529 colors
[0] == (wxr_formats_template
[i
].redMask
<< wxr_formats_template
[i
].red
) &&
530 colors
[1] == (wxr_formats_template
[i
].greenMask
<< wxr_formats_template
[i
].green
) &&
531 colors
[2] == (wxr_formats_template
[i
].blueMask
<< wxr_formats_template
[i
].blue
))
536 if (info
->bmiHeader
.biCompression
!= BI_RGB
) break;
537 if (info
->bmiHeader
.biBitCount
== 16) return WXR_FORMAT_X1R5G5B5
;
538 return use_alpha
? WXR_FORMAT_A8R8G8B8
: WXR_FORMAT_X8R8G8B8
;
540 return WXR_INVALID_FORMAT
;
543 /* Set the x/y scaling and x/y offsets in the transformation matrix of the source picture */
544 static void set_xrender_transformation(Picture src_pict
, double xscale
, double yscale
, int xoffset
, int yoffset
)
546 #ifdef HAVE_XRENDERSETPICTURETRANSFORM
547 XTransform xform
= {{
548 { XDoubleToFixed(xscale
), XDoubleToFixed(0), XDoubleToFixed(xoffset
) },
549 { XDoubleToFixed(0), XDoubleToFixed(yscale
), XDoubleToFixed(yoffset
) },
550 { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
553 pXRenderSetPictureTransform(gdi_display
, src_pict
, &xform
);
557 /* check if we can use repeating instead of scaling for the specified source DC */
558 static BOOL
use_source_repeat( struct xrender_physdev
*dev
)
560 return (dev
->x11dev
->bitmap
&&
561 dev
->x11dev
->drawable_rect
.right
- dev
->x11dev
->drawable_rect
.left
== 1 &&
562 dev
->x11dev
->drawable_rect
.bottom
- dev
->x11dev
->drawable_rect
.top
== 1);
565 static Picture
get_xrender_picture( struct xrender_physdev
*dev
, HRGN clip_rgn
, const RECT
*clip_rect
)
567 if (!dev
->pict
&& dev
->pict_format
)
569 XRenderPictureAttributes pa
;
572 pa
.subwindow_mode
= IncludeInferiors
;
573 dev
->pict
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
574 dev
->pict_format
, CPSubwindowMode
, &pa
);
576 TRACE( "Allocing pict=%lx dc=%p drawable=%08lx\n",
577 dev
->pict
, dev
->dev
.hdc
, dev
->x11dev
->drawable
);
578 dev
->update_clip
= TRUE
;
581 if (dev
->update_clip
)
588 rgn
= CreateRectRgnIndirect( clip_rect
);
589 if (clip_rgn
) CombineRgn( rgn
, rgn
, clip_rgn
, RGN_AND
);
590 CombineRgn( rgn
, rgn
, dev
->x11dev
->region
, RGN_AND
);
594 rgn
= CreateRectRgn( 0, 0, 0, 0 );
595 CombineRgn( rgn
, clip_rgn
, dev
->x11dev
->region
, RGN_AND
);
598 if ((clip_data
= X11DRV_GetRegionData( rgn
? rgn
: dev
->x11dev
->region
, 0 )))
601 pXRenderSetPictureClipRectangles( gdi_display
, dev
->pict
,
602 dev
->x11dev
->dc_rect
.left
, dev
->x11dev
->dc_rect
.top
,
603 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
605 HeapFree( GetProcessHeap(), 0, clip_data
);
607 dev
->update_clip
= (rgn
!= 0); /* have to update again if we are using a custom region */
608 if (rgn
) DeleteObject( rgn
);
613 static Picture
get_xrender_picture_source( struct xrender_physdev
*dev
, BOOL repeat
)
615 if (!dev
->pict_src
&& dev
->pict_format
)
617 XRenderPictureAttributes pa
;
620 pa
.subwindow_mode
= IncludeInferiors
;
621 pa
.repeat
= repeat
? RepeatNormal
: RepeatNone
;
622 dev
->pict_src
= pXRenderCreatePicture( gdi_display
, dev
->x11dev
->drawable
,
623 dev
->pict_format
, CPSubwindowMode
|CPRepeat
, &pa
);
626 TRACE("Allocing pict_src=%lx dc=%p drawable=%08lx repeat=%u\n",
627 dev
->pict_src
, dev
->dev
.hdc
, dev
->x11dev
->drawable
, pa
.repeat
);
630 return dev
->pict_src
;
633 static void free_xrender_picture( struct xrender_physdev
*dev
)
635 if (dev
->pict
|| dev
->pict_src
)
638 XFlush( gdi_display
);
641 TRACE("freeing pict = %lx dc = %p\n", dev
->pict
, dev
->dev
.hdc
);
642 pXRenderFreePicture(gdi_display
, dev
->pict
);
647 TRACE("freeing pict = %lx dc = %p\n", dev
->pict_src
, dev
->dev
.hdc
);
648 pXRenderFreePicture(gdi_display
, dev
->pict_src
);
655 /* return a mask picture used to force alpha to 0 */
656 static Picture
get_no_alpha_mask(void)
658 static Pixmap pixmap
;
664 XRenderPictureAttributes pa
;
667 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
668 pa
.repeat
= RepeatNormal
;
669 pa
.component_alpha
= True
;
670 pict
= pXRenderCreatePicture( gdi_display
, pixmap
, pict_formats
[WXR_FORMAT_A8R8G8B8
],
671 CPRepeat
|CPComponentAlpha
, &pa
);
672 col
.red
= col
.green
= col
.blue
= 0xffff;
674 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
680 static BOOL
fontcmp(LFANDSIZE
*p1
, LFANDSIZE
*p2
)
682 if(p1
->hash
!= p2
->hash
) return TRUE
;
683 if(memcmp(&p1
->devsize
, &p2
->devsize
, sizeof(p1
->devsize
))) return TRUE
;
684 if(memcmp(&p1
->xform
, &p2
->xform
, sizeof(p1
->xform
))) return TRUE
;
685 if(memcmp(&p1
->lf
, &p2
->lf
, offsetof(LOGFONTW
, lfFaceName
))) return TRUE
;
686 return strcmpiW(p1
->lf
.lfFaceName
, p2
->lf
.lfFaceName
);
690 static void walk_cache(void)
694 EnterCriticalSection(&xrender_cs
);
695 for(i
=mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
696 TRACE("item %d\n", i
);
697 LeaveCriticalSection(&xrender_cs
);
701 static int LookupEntry(LFANDSIZE
*plfsz
)
705 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
707 if(glyphsetCache
[i
].count
== -1) break; /* reached free list so stop */
709 if(!fontcmp(&glyphsetCache
[i
].lfsz
, plfsz
)) {
710 glyphsetCache
[i
].count
++;
712 glyphsetCache
[prev_i
].next
= glyphsetCache
[i
].next
;
713 glyphsetCache
[i
].next
= mru
;
716 TRACE("found font in cache %d\n", i
);
721 TRACE("font not in cache\n");
725 static void FreeEntry(int entry
)
729 for(format
= 0; format
< AA_MAXVALUE
; format
++) {
730 gsCacheEntryFormat
* formatEntry
;
732 if( !glyphsetCache
[entry
].format
[format
] )
735 formatEntry
= glyphsetCache
[entry
].format
[format
];
737 if(formatEntry
->glyphset
) {
739 pXRenderFreeGlyphSet(gdi_display
, formatEntry
->glyphset
);
741 formatEntry
->glyphset
= 0;
743 if(formatEntry
->nrealized
) {
744 HeapFree(GetProcessHeap(), 0, formatEntry
->realized
);
745 formatEntry
->realized
= NULL
;
746 if(formatEntry
->bitmaps
) {
747 for(i
= 0; i
< formatEntry
->nrealized
; i
++)
748 HeapFree(GetProcessHeap(), 0, formatEntry
->bitmaps
[i
]);
749 HeapFree(GetProcessHeap(), 0, formatEntry
->bitmaps
);
750 formatEntry
->bitmaps
= NULL
;
752 HeapFree(GetProcessHeap(), 0, formatEntry
->gis
);
753 formatEntry
->gis
= NULL
;
754 formatEntry
->nrealized
= 0;
757 HeapFree(GetProcessHeap(), 0, formatEntry
);
758 glyphsetCache
[entry
].format
[format
] = NULL
;
762 static int AllocEntry(void)
764 int best
= -1, prev_best
= -1, i
, prev_i
= -1;
767 assert(glyphsetCache
[lastfree
].count
== -1);
768 glyphsetCache
[lastfree
].count
= 1;
770 lastfree
= glyphsetCache
[lastfree
].next
;
772 glyphsetCache
[best
].next
= mru
;
775 TRACE("empty space at %d, next lastfree = %d\n", mru
, lastfree
);
779 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
) {
780 if(glyphsetCache
[i
].count
== 0) {
788 TRACE("freeing unused glyphset at cache %d\n", best
);
790 glyphsetCache
[best
].count
= 1;
792 glyphsetCache
[prev_best
].next
= glyphsetCache
[best
].next
;
793 glyphsetCache
[best
].next
= mru
;
801 TRACE("Growing cache\n");
804 glyphsetCache
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
806 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
807 * sizeof(*glyphsetCache
));
809 glyphsetCache
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
810 (glyphsetCacheSize
+ INIT_CACHE_SIZE
)
811 * sizeof(*glyphsetCache
));
813 for(best
= i
= glyphsetCacheSize
; i
< glyphsetCacheSize
+ INIT_CACHE_SIZE
;
815 glyphsetCache
[i
].next
= i
+ 1;
816 glyphsetCache
[i
].count
= -1;
818 glyphsetCache
[i
-1].next
= -1;
819 glyphsetCacheSize
+= INIT_CACHE_SIZE
;
821 lastfree
= glyphsetCache
[best
].next
;
822 glyphsetCache
[best
].count
= 1;
823 glyphsetCache
[best
].next
= mru
;
825 TRACE("new free cache slot at %d\n", mru
);
829 static BOOL
get_gasp_flags(HDC hdc
, WORD
*flags
)
839 size
= GetFontData(hdc
, MS_GASP_TAG
, 0, NULL
, 0);
840 if(size
== GDI_ERROR
)
843 gasp
= buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
844 GetFontData(hdc
, MS_GASP_TAG
, 0, gasp
, size
);
846 GetTextMetricsW(hdc
, &tm
);
847 ppem
= abs(X11DRV_YWStoDS(hdc
, tm
.tmAscent
+ tm
.tmDescent
- tm
.tmInternalLeading
));
850 num_recs
= get_be_word(*gasp
);
854 *flags
= get_be_word(*(gasp
+ 1));
855 if(ppem
<= get_be_word(*gasp
))
859 TRACE("got flags %04x for ppem %d\n", *flags
, ppem
);
861 HeapFree(GetProcessHeap(), 0, buffer
);
865 static AA_Type
get_antialias_type( HDC hdc
, BOOL subpixel
, BOOL hinter
)
869 UINT font_smoothing_type
, font_smoothing_orientation
;
871 if (X11DRV_XRender_Installed
&& subpixel
&&
872 SystemParametersInfoW( SPI_GETFONTSMOOTHINGTYPE
, 0, &font_smoothing_type
, 0) &&
873 font_smoothing_type
== FE_FONTSMOOTHINGCLEARTYPE
)
875 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHINGORIENTATION
, 0,
876 &font_smoothing_orientation
, 0) &&
877 font_smoothing_orientation
== FE_FONTSMOOTHINGORIENTATIONBGR
)
884 If the monitor is in portrait mode, ClearType is disabled in the MS Windows (MSDN).
885 But, Wine's subpixel rendering can support the portrait mode.
888 else if (!hinter
|| !get_gasp_flags(hdc
, &flags
) || flags
& GASP_DOGRAY
)
896 static int GetCacheEntry( HDC hdc
, LFANDSIZE
*plfsz
)
901 static int hinter
= -1;
902 static int subpixel
= -1;
905 if((ret
= LookupEntry(plfsz
)) != -1) return ret
;
908 entry
= glyphsetCache
+ ret
;
909 entry
->lfsz
= *plfsz
;
910 for( format
= 0; format
< AA_MAXVALUE
; format
++ ) {
911 assert( !entry
->format
[format
] );
914 if(antialias
&& plfsz
->lf
.lfQuality
!= NONANTIALIASED_QUALITY
)
916 if(hinter
== -1 || subpixel
== -1)
918 RASTERIZER_STATUS status
;
919 GetRasterizerCaps(&status
, sizeof(status
));
920 hinter
= status
.wFlags
& WINE_TT_HINTER_ENABLED
;
921 subpixel
= status
.wFlags
& WINE_TT_SUBPIXEL_RENDERING_ENABLED
;
924 switch (plfsz
->lf
.lfQuality
)
926 case ANTIALIASED_QUALITY
:
927 entry
->aa_default
= get_antialias_type( hdc
, FALSE
, hinter
);
928 return ret
; /* ignore further configuration */
929 case CLEARTYPE_QUALITY
:
930 case CLEARTYPE_NATURAL_QUALITY
:
931 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
933 case DEFAULT_QUALITY
:
937 if ( SystemParametersInfoW( SPI_GETFONTSMOOTHING
, 0, &font_smoothing
, 0) &&
940 entry
->aa_default
= get_antialias_type( hdc
, subpixel
, hinter
);
943 entry
->aa_default
= AA_None
;
947 font_smoothing
= TRUE
; /* default to enabled */
948 #ifdef SONAME_LIBFONTCONFIG
949 if (fontconfig_installed
)
951 FcPattern
*match
, *pattern
= pFcPatternCreate();
953 char family
[LF_FACESIZE
* 4];
955 WideCharToMultiByte( CP_UTF8
, 0, plfsz
->lf
.lfFaceName
, -1, family
, sizeof(family
), NULL
, NULL
);
956 pFcPatternAddString( pattern
, FC_FAMILY
, (FcChar8
*)family
);
957 if (plfsz
->lf
.lfWeight
!= FW_DONTCARE
)
960 switch (plfsz
->lf
.lfWeight
)
962 case FW_THIN
: weight
= FC_WEIGHT_THIN
; break;
963 case FW_EXTRALIGHT
: weight
= FC_WEIGHT_EXTRALIGHT
; break;
964 case FW_LIGHT
: weight
= FC_WEIGHT_LIGHT
; break;
965 case FW_NORMAL
: weight
= FC_WEIGHT_NORMAL
; break;
966 case FW_MEDIUM
: weight
= FC_WEIGHT_MEDIUM
; break;
967 case FW_SEMIBOLD
: weight
= FC_WEIGHT_SEMIBOLD
; break;
968 case FW_BOLD
: weight
= FC_WEIGHT_BOLD
; break;
969 case FW_EXTRABOLD
: weight
= FC_WEIGHT_EXTRABOLD
; break;
970 case FW_HEAVY
: weight
= FC_WEIGHT_HEAVY
; break;
971 default: weight
= (plfsz
->lf
.lfWeight
- 80) / 4; break;
973 pFcPatternAddInteger( pattern
, FC_WEIGHT
, weight
);
975 pFcPatternAddInteger( pattern
, FC_SLANT
, plfsz
->lf
.lfItalic
? FC_SLANT_ITALIC
: FC_SLANT_ROMAN
);
976 pFcConfigSubstitute( NULL
, pattern
, FcMatchPattern
);
977 pFcDefaultSubstitute( pattern
);
978 if ((match
= pFcFontMatch( NULL
, pattern
, &result
)))
983 if (pFcPatternGetBool( match
, FC_ANTIALIAS
, 0, &antialias
) != FcResultMatch
)
985 if (pFcPatternGetInteger( match
, FC_RGBA
, 0, &rgba
) == FcResultMatch
)
988 if (pFcPatternGetString( match
, FC_FILE
, 0, &file
) != FcResultMatch
) file
= NULL
;
990 TRACE( "fontconfig returned rgba %u antialias %u for font %s file %s\n",
991 rgba
, antialias
, debugstr_w(plfsz
->lf
.lfFaceName
), debugstr_a((char *)file
) );
995 case FC_RGBA_RGB
: entry
->aa_default
= AA_RGB
; break;
996 case FC_RGBA_BGR
: entry
->aa_default
= AA_BGR
; break;
997 case FC_RGBA_VRGB
: entry
->aa_default
= AA_VRGB
; break;
998 case FC_RGBA_VBGR
: entry
->aa_default
= AA_VBGR
; break;
999 case FC_RGBA_NONE
: entry
->aa_default
= AA_Grey
; break;
1002 if (!antialias
) font_smoothing
= FALSE
;
1003 pFcPatternDestroy( match
);
1005 pFcPatternDestroy( pattern
);
1007 #endif /* SONAME_LIBFONTCONFIG */
1009 /* now check Xft resources */
1012 BOOL antialias
= TRUE
;
1015 if ((value
= XGetDefault( gdi_display
, "Xft", "antialias" )))
1017 if (tolower(value
[0]) == 'f' || tolower(value
[0]) == 'n' ||
1018 value
[0] == '0' || !strcasecmp( value
, "off" ))
1021 if ((value
= XGetDefault( gdi_display
, "Xft", "rgba" )))
1023 TRACE( "Xft resource returned rgba '%s' antialias %u\n", value
, antialias
);
1024 if (!strcmp( value
, "rgb" )) entry
->aa_default
= AA_RGB
;
1025 else if (!strcmp( value
, "bgr" )) entry
->aa_default
= AA_BGR
;
1026 else if (!strcmp( value
, "vrgb" )) entry
->aa_default
= AA_VRGB
;
1027 else if (!strcmp( value
, "vbgr" )) entry
->aa_default
= AA_VBGR
;
1028 else if (!strcmp( value
, "none" )) entry
->aa_default
= AA_Grey
;
1030 wine_tsx11_unlock();
1031 if (!antialias
) font_smoothing
= FALSE
;
1034 if (!font_smoothing
) entry
->aa_default
= AA_None
;
1036 /* we can't support subpixel without xrender */
1037 if (!X11DRV_XRender_Installed
&& entry
->aa_default
> AA_Grey
) entry
->aa_default
= AA_Grey
;
1040 entry
->aa_default
= AA_None
;
1045 static void dec_ref_cache(int index
)
1048 TRACE("dec'ing entry %d to %d\n", index
, glyphsetCache
[index
].count
- 1);
1049 assert(glyphsetCache
[index
].count
> 0);
1050 glyphsetCache
[index
].count
--;
1053 static void lfsz_calc_hash(LFANDSIZE
*plfsz
)
1055 DWORD hash
= 0, *ptr
, two_chars
;
1059 hash
^= plfsz
->devsize
.cx
;
1060 hash
^= plfsz
->devsize
.cy
;
1061 for(i
= 0, ptr
= (DWORD
*)&plfsz
->xform
; i
< sizeof(XFORM
)/sizeof(DWORD
); i
++, ptr
++)
1063 for(i
= 0, ptr
= (DWORD
*)&plfsz
->lf
; i
< 7; i
++, ptr
++)
1065 for(i
= 0, ptr
= (DWORD
*)plfsz
->lf
.lfFaceName
; i
< LF_FACESIZE
/2; i
++, ptr
++) {
1067 pwc
= (WCHAR
*)&two_chars
;
1069 *pwc
= toupperW(*pwc
);
1071 *pwc
= toupperW(*pwc
);
1079 /***********************************************************************
1080 * X11DRV_XRender_Finalize
1082 void X11DRV_XRender_Finalize(void)
1086 EnterCriticalSection(&xrender_cs
);
1087 for(i
= mru
; i
>= 0; i
= glyphsetCache
[i
].next
)
1089 LeaveCriticalSection(&xrender_cs
);
1092 /**********************************************************************
1093 * xrenderdrv_SelectFont
1095 static HFONT
xrenderdrv_SelectFont( PHYSDEV dev
, HFONT hfont
, HANDLE gdiFont
)
1097 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1100 if (!GetObjectW( hfont
, sizeof(lfsz
.lf
), &lfsz
.lf
)) return HGDI_ERROR
;
1104 dev
= GET_NEXT_PHYSDEV( dev
, pSelectFont
);
1105 return dev
->funcs
->pSelectFont( dev
, hfont
, gdiFont
);
1108 TRACE("h=%d w=%d weight=%d it=%d charset=%d name=%s\n",
1109 lfsz
.lf
.lfHeight
, lfsz
.lf
.lfWidth
, lfsz
.lf
.lfWeight
,
1110 lfsz
.lf
.lfItalic
, lfsz
.lf
.lfCharSet
, debugstr_w(lfsz
.lf
.lfFaceName
));
1111 lfsz
.lf
.lfWidth
= abs( lfsz
.lf
.lfWidth
);
1112 lfsz
.devsize
.cx
= X11DRV_XWStoDS( dev
->hdc
, lfsz
.lf
.lfWidth
);
1113 lfsz
.devsize
.cy
= X11DRV_YWStoDS( dev
->hdc
, lfsz
.lf
.lfHeight
);
1115 GetTransform( dev
->hdc
, 0x204, &lfsz
.xform
);
1116 TRACE("font transform %f %f %f %f\n", lfsz
.xform
.eM11
, lfsz
.xform
.eM12
,
1117 lfsz
.xform
.eM21
, lfsz
.xform
.eM22
);
1119 /* Not used fields, would break hashing */
1120 lfsz
.xform
.eDx
= lfsz
.xform
.eDy
= 0;
1122 lfsz_calc_hash(&lfsz
);
1124 EnterCriticalSection(&xrender_cs
);
1125 if (physdev
->cache_index
!= -1)
1126 dec_ref_cache( physdev
->cache_index
);
1127 physdev
->cache_index
= GetCacheEntry( dev
->hdc
, &lfsz
);
1128 LeaveCriticalSection(&xrender_cs
);
1129 physdev
->x11dev
->has_gdi_font
= TRUE
;
1133 static BOOL
create_xrender_dc( PHYSDEV
*pdev
, enum wxr_format format
)
1135 X11DRV_PDEVICE
*x11dev
= get_x11drv_dev( *pdev
);
1136 struct xrender_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
1138 if (!physdev
) return FALSE
;
1139 physdev
->x11dev
= x11dev
;
1140 physdev
->cache_index
= -1;
1141 physdev
->format
= format
;
1142 physdev
->pict_format
= pict_formats
[format
];
1143 push_dc_driver( pdev
, &physdev
->dev
, &xrender_funcs
);
1147 /* store the color mask data in the bitmap info structure */
1148 static void set_color_info( XRenderPictFormat
*format
, BITMAPINFO
*info
)
1150 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1152 info
->bmiHeader
.biPlanes
= 1;
1153 info
->bmiHeader
.biBitCount
= pixmap_formats
[format
->depth
]->bits_per_pixel
;
1154 info
->bmiHeader
.biCompression
= BI_RGB
;
1155 info
->bmiHeader
.biClrUsed
= 0;
1157 switch (info
->bmiHeader
.biBitCount
)
1160 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1161 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1162 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1163 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1166 colors
[0] = format
->direct
.redMask
<< format
->direct
.red
;
1167 colors
[1] = format
->direct
.greenMask
<< format
->direct
.green
;
1168 colors
[2] = format
->direct
.blueMask
<< format
->direct
.blue
;
1169 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1170 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1176 /**********************************************************************
1177 * xrenderdrv_CreateDC
1179 static BOOL
xrenderdrv_CreateDC( PHYSDEV
*pdev
, LPCWSTR driver
, LPCWSTR device
,
1180 LPCWSTR output
, const DEVMODEW
* initData
)
1182 return create_xrender_dc( pdev
, default_format
);
1185 /**********************************************************************
1186 * xrenderdrv_CreateCompatibleDC
1188 static BOOL
xrenderdrv_CreateCompatibleDC( PHYSDEV orig
, PHYSDEV
*pdev
)
1190 if (orig
) /* chain to x11drv first */
1192 orig
= GET_NEXT_PHYSDEV( orig
, pCreateCompatibleDC
);
1193 if (!orig
->funcs
->pCreateCompatibleDC( orig
, pdev
)) return FALSE
;
1195 /* otherwise we have been called by x11drv */
1197 return create_xrender_dc( pdev
, WXR_FORMAT_MONO
);
1200 /**********************************************************************
1201 * xrenderdrv_DeleteDC
1203 static BOOL
xrenderdrv_DeleteDC( PHYSDEV dev
)
1205 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1207 free_xrender_picture( physdev
);
1209 EnterCriticalSection( &xrender_cs
);
1210 if (physdev
->cache_index
!= -1) dec_ref_cache( physdev
->cache_index
);
1211 LeaveCriticalSection( &xrender_cs
);
1213 HeapFree( GetProcessHeap(), 0, physdev
);
1217 /**********************************************************************
1218 * xrenderdrv_ExtEscape
1220 static INT
xrenderdrv_ExtEscape( PHYSDEV dev
, INT escape
, INT in_count
, LPCVOID in_data
,
1221 INT out_count
, LPVOID out_data
)
1223 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1225 dev
= GET_NEXT_PHYSDEV( dev
, pExtEscape
);
1227 if (escape
== X11DRV_ESCAPE
&& in_data
&& in_count
>= sizeof(enum x11drv_escape_codes
))
1229 if (*(const enum x11drv_escape_codes
*)in_data
== X11DRV_SET_DRAWABLE
)
1231 BOOL ret
= dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1232 if (ret
) free_xrender_picture( physdev
); /* pict format doesn't change, only drawable */
1236 return dev
->funcs
->pExtEscape( dev
, escape
, in_count
, in_data
, out_count
, out_data
);
1239 /****************************************************************************
1240 * xrenderdrv_CreateBitmap
1242 static BOOL
xrenderdrv_CreateBitmap( PHYSDEV dev
, HBITMAP hbitmap
)
1244 enum wxr_format format
= WXR_INVALID_FORMAT
;
1247 if (!GetObjectW( hbitmap
, sizeof(bitmap
), &bitmap
)) return FALSE
;
1249 if (bitmap
.bmPlanes
== 1 && bitmap
.bmBitsPixel
== screen_bpp
)
1251 switch (bitmap
.bmBitsPixel
)
1253 case 16: format
= WXR_FORMAT_R5G6B5
; break;
1254 case 24: format
= WXR_FORMAT_R8G8B8
; break;
1255 case 32: format
= WXR_FORMAT_A8R8G8B8
; break;
1259 if (pict_formats
[format
])
1260 return X11DRV_create_phys_bitmap( hbitmap
, &bitmap
, pict_formats
[format
]->depth
,
1261 TRUE
, &wxr_color_shifts
[format
] );
1263 dev
= GET_NEXT_PHYSDEV( dev
, pCreateBitmap
);
1264 return dev
->funcs
->pCreateBitmap( dev
, hbitmap
);
1267 /****************************************************************************
1268 * xrenderdrv_DeleteBitmap
1270 static BOOL
xrenderdrv_DeleteBitmap( HBITMAP hbitmap
)
1272 return X11DRV_DeleteBitmap( hbitmap
);
1275 /***********************************************************************
1276 * xrenderdrv_SelectBitmap
1278 static HBITMAP
xrenderdrv_SelectBitmap( PHYSDEV dev
, HBITMAP hbitmap
)
1281 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1283 dev
= GET_NEXT_PHYSDEV( dev
, pSelectBitmap
);
1284 ret
= dev
->funcs
->pSelectBitmap( dev
, hbitmap
);
1287 free_xrender_picture( physdev
);
1288 physdev
->format
= get_xrender_format_from_color_shifts( physdev
->x11dev
->depth
,
1289 physdev
->x11dev
->color_shifts
);
1290 physdev
->pict_format
= pict_formats
[physdev
->format
];
1295 /***********************************************************************
1296 * xrenderdrv_GetImage
1298 static DWORD
xrenderdrv_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1299 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
1301 if (hbitmap
) return X11DRV_GetImage( dev
, hbitmap
, info
, bits
, src
);
1302 dev
= GET_NEXT_PHYSDEV( dev
, pGetImage
);
1303 return dev
->funcs
->pGetImage( dev
, hbitmap
, info
, bits
, src
);
1306 /***********************************************************************
1307 * xrenderdrv_SetDeviceClipping
1309 static void xrenderdrv_SetDeviceClipping( PHYSDEV dev
, HRGN vis_rgn
, HRGN clip_rgn
)
1311 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1313 physdev
->update_clip
= TRUE
;
1315 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
1316 dev
->funcs
->pSetDeviceClipping( dev
, vis_rgn
, clip_rgn
);
1320 BOOL
X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP
*physBitmap
, int bits_pixel
, const DIBSECTION
*dib
)
1322 XRenderPictFormat
*pict_format
;
1324 const DWORD
*bitfields
;
1325 static const DWORD bitfields_32
[3] = {0xff0000, 0x00ff00, 0x0000ff};
1326 static const DWORD bitfields_16
[3] = {0x7c00, 0x03e0, 0x001f};
1329 /* When XRender is not around we can only use the screen_depth and when needed we perform depth conversion
1330 * in software. Further we also return the screen depth for paletted formats or TrueColor formats with a low
1331 * number of bits because XRender can't handle paletted formats and 8-bit TrueColor does not exist for XRender. */
1332 if (!X11DRV_XRender_Installed
|| bits_pixel
<= 8)
1335 if(dib
->dsBmih
.biCompression
== BI_BITFIELDS
)
1336 bitfields
= dib
->dsBitfields
;
1337 else if(bits_pixel
== 24 || bits_pixel
== 32)
1338 bitfields
= bitfields_32
;
1340 bitfields
= bitfields_16
;
1342 X11DRV_PALETTE_ComputeColorShifts(&shifts
, bitfields
[0], bitfields
[1], bitfields
[2]);
1343 pict_format
= pict_formats
[get_xrender_format_from_color_shifts(dib
->dsBm
.bmBitsPixel
, &shifts
)];
1345 /* Common formats should be in our picture format table. */
1348 TRACE("Unhandled dibsection format bpp=%d, redMask=%x, greenMask=%x, blueMask=%x\n",
1349 dib
->dsBm
.bmBitsPixel
, bitfields
[0], bitfields
[1], bitfields
[2]);
1353 physBitmap
->depth
= pict_format
->depth
;
1354 physBitmap
->trueColor
= TRUE
;
1355 physBitmap
->color_shifts
= shifts
;
1359 /************************************************************************
1362 * Helper to ExtTextOut. Must be called inside xrender_cs
1364 static void UploadGlyph(struct xrender_physdev
*physDev
, int glyph
, AA_Type format
)
1366 unsigned int buflen
;
1371 gsCacheEntry
*entry
= glyphsetCache
+ physDev
->cache_index
;
1372 gsCacheEntryFormat
*formatEntry
;
1373 UINT ggo_format
= GGO_GLYPH_INDEX
;
1374 enum wxr_format wxr_format
;
1375 static const char zero
[4];
1376 static const MAT2 identity
= { {0,1},{0,0},{0,0},{0,1} };
1380 ggo_format
|= WINE_GGO_GRAY16_BITMAP
;
1383 ggo_format
|= WINE_GGO_HRGB_BITMAP
;
1386 ggo_format
|= WINE_GGO_HBGR_BITMAP
;
1389 ggo_format
|= WINE_GGO_VRGB_BITMAP
;
1392 ggo_format
|= WINE_GGO_VBGR_BITMAP
;
1396 ERR("aa = %d - not implemented\n", format
);
1398 ggo_format
|= GGO_BITMAP
;
1402 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1403 if(buflen
== GDI_ERROR
) {
1404 if(format
!= AA_None
) {
1406 entry
->aa_default
= AA_None
;
1407 ggo_format
= GGO_GLYPH_INDEX
| GGO_BITMAP
;
1408 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, 0, NULL
, &identity
);
1410 if(buflen
== GDI_ERROR
) {
1411 WARN("GetGlyphOutlineW failed using default glyph\n");
1412 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0, ggo_format
, &gm
, 0, NULL
, &identity
);
1413 if(buflen
== GDI_ERROR
) {
1414 WARN("GetGlyphOutlineW failed for default glyph trying for space\n");
1415 buflen
= GetGlyphOutlineW(physDev
->dev
.hdc
, 0x20, ggo_format
, &gm
, 0, NULL
, &identity
);
1416 if(buflen
== GDI_ERROR
) {
1417 ERR("GetGlyphOutlineW for all attempts unable to upload a glyph\n");
1422 TRACE("Turning off antialiasing for this monochrome font\n");
1425 /* If there is nothing for the current type, we create the entry. */
1426 if( !entry
->format
[format
] ) {
1427 entry
->format
[format
] = HeapAlloc(GetProcessHeap(),
1429 sizeof(gsCacheEntryFormat
));
1431 formatEntry
= entry
->format
[format
];
1433 if(formatEntry
->nrealized
<= glyph
) {
1434 formatEntry
->nrealized
= (glyph
/ 128 + 1) * 128;
1436 if (formatEntry
->realized
)
1437 formatEntry
->realized
= HeapReAlloc(GetProcessHeap(),
1439 formatEntry
->realized
,
1440 formatEntry
->nrealized
* sizeof(BOOL
));
1442 formatEntry
->realized
= HeapAlloc(GetProcessHeap(),
1444 formatEntry
->nrealized
* sizeof(BOOL
));
1446 if(!X11DRV_XRender_Installed
) {
1447 if (formatEntry
->bitmaps
)
1448 formatEntry
->bitmaps
= HeapReAlloc(GetProcessHeap(),
1450 formatEntry
->bitmaps
,
1451 formatEntry
->nrealized
* sizeof(formatEntry
->bitmaps
[0]));
1453 formatEntry
->bitmaps
= HeapAlloc(GetProcessHeap(),
1455 formatEntry
->nrealized
* sizeof(formatEntry
->bitmaps
[0]));
1457 if (formatEntry
->gis
)
1458 formatEntry
->gis
= HeapReAlloc(GetProcessHeap(),
1461 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1463 formatEntry
->gis
= HeapAlloc(GetProcessHeap(),
1465 formatEntry
->nrealized
* sizeof(formatEntry
->gis
[0]));
1469 if(formatEntry
->glyphset
== 0 && X11DRV_XRender_Installed
) {
1472 wxr_format
= WXR_FORMAT_GRAY
;
1479 wxr_format
= WXR_FORMAT_A8R8G8B8
;
1483 ERR("aa = %d - not implemented\n", format
);
1485 wxr_format
= WXR_FORMAT_MONO
;
1490 formatEntry
->font_format
= pict_formats
[wxr_format
];
1491 formatEntry
->glyphset
= pXRenderCreateGlyphSet(gdi_display
, formatEntry
->font_format
);
1492 wine_tsx11_unlock();
1496 buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buflen
);
1497 GetGlyphOutlineW(physDev
->dev
.hdc
, glyph
, ggo_format
, &gm
, buflen
, buf
, &identity
);
1498 formatEntry
->realized
[glyph
] = TRUE
;
1500 TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%d,%d\n",
1502 gm
.gmBlackBoxX
, gm
.gmBlackBoxY
, gm
.gmCellIncX
, gm
.gmCellIncY
,
1503 gm
.gmptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.y
);
1505 gi
.width
= gm
.gmBlackBoxX
;
1506 gi
.height
= gm
.gmBlackBoxY
;
1507 gi
.x
= -gm
.gmptGlyphOrigin
.x
;
1508 gi
.y
= gm
.gmptGlyphOrigin
.y
;
1509 gi
.xOff
= gm
.gmCellIncX
;
1510 gi
.yOff
= gm
.gmCellIncY
;
1512 if(TRACE_ON(xrender
)) {
1515 unsigned char *line
;
1517 if(format
== AA_None
) {
1518 pitch
= ((gi
.width
+ 31) / 32) * 4;
1519 for(i
= 0; i
< gi
.height
; i
++) {
1520 line
= (unsigned char*) buf
+ i
* pitch
;
1522 for(j
= 0; j
< pitch
* 8; j
++) {
1523 strcat(output
, (line
[j
/ 8] & (1 << (7 - (j
% 8)))) ? "#" : " ");
1525 TRACE("%s\n", output
);
1528 static const char blks
[] = " .:;!o*#";
1532 pitch
= ((gi
.width
+ 3) / 4) * 4;
1533 for(i
= 0; i
< gi
.height
; i
++) {
1534 line
= (unsigned char*) buf
+ i
* pitch
;
1536 for(j
= 0; j
< pitch
; j
++) {
1537 str
[0] = blks
[line
[j
] >> 5];
1538 strcat(output
, str
);
1540 TRACE("%s\n", output
);
1546 if(formatEntry
->glyphset
) {
1547 if(format
== AA_None
&& BitmapBitOrder(gdi_display
) != MSBFirst
) {
1548 unsigned char *byte
= (unsigned char*) buf
, c
;
1554 /* magic to flip bit order */
1555 c
= ((c
<< 1) & 0xaa) | ((c
>> 1) & 0x55);
1556 c
= ((c
<< 2) & 0xcc) | ((c
>> 2) & 0x33);
1557 c
= ((c
<< 4) & 0xf0) | ((c
>> 4) & 0x0f);
1562 else if ( format
!= AA_Grey
&&
1563 ImageByteOrder (gdi_display
) != NATIVE_BYTE_ORDER
)
1565 unsigned int i
, *data
= (unsigned int *)buf
;
1566 for (i
= buflen
/ sizeof(int); i
; i
--, data
++) *data
= RtlUlongByteSwap(*data
);
1571 XRenderCompositeText seems to ignore 0x0 glyphs when
1572 AA_None, which means we lose the advance width of glyphs
1573 like the space. We'll pretend that such glyphs are 1x1
1578 gi
.width
= gi
.height
= 1;
1581 pXRenderAddGlyphs(gdi_display
, formatEntry
->glyphset
, &gid
, &gi
, 1,
1582 buflen
? buf
: zero
, buflen
? buflen
: sizeof(zero
));
1583 wine_tsx11_unlock();
1584 HeapFree(GetProcessHeap(), 0, buf
);
1586 formatEntry
->bitmaps
[glyph
] = buf
;
1589 formatEntry
->gis
[glyph
] = gi
;
1592 static void SharpGlyphMono(struct xrender_physdev
*physDev
, INT x
, INT y
,
1593 void *bitmap
, XGlyphInfo
*gi
)
1595 unsigned char *srcLine
= bitmap
, *src
;
1596 unsigned char bits
, bitsMask
;
1597 int width
= gi
->width
;
1598 int stride
= ((width
+ 31) & ~31) >> 3;
1599 int height
= gi
->height
;
1603 TRACE("%d, %d\n", x
, y
);
1612 bitsMask
= 0x80; /* FreeType is always MSB first */
1618 if (bits
& bitsMask
)
1626 bitsMask
= bitsMask
>> 1;
1632 } while (bits
& bitsMask
);
1633 XFillRectangle (gdi_display
, physDev
->x11dev
->drawable
,
1634 physDev
->x11dev
->gc
, xspan
, y
, lenspan
, 1);
1646 bitsMask
= bitsMask
>> 1;
1652 } while (!(bits
& bitsMask
));
1659 static void SharpGlyphGray(struct xrender_physdev
*physDev
, INT x
, INT y
,
1660 void *bitmap
, XGlyphInfo
*gi
)
1662 unsigned char *srcLine
= bitmap
, *src
, bits
;
1663 int width
= gi
->width
;
1664 int stride
= ((width
+ 3) & ~3);
1665 int height
= gi
->height
;
1690 } while (bits
>= 0x80);
1691 XFillRectangle (gdi_display
, physDev
->x11dev
->drawable
,
1692 physDev
->x11dev
->gc
, xspan
, y
, lenspan
, 1);
1705 } while (bits
< 0x80);
1713 static void ExamineBitfield (DWORD mask
, int *shift
, int *len
)
1718 while ((mask
& 1) == 0)
1724 while ((mask
& 1) == 1)
1733 static DWORD
GetField (DWORD pixel
, int shift
, int len
)
1735 pixel
= pixel
& (((1 << (len
)) - 1) << shift
);
1736 pixel
= pixel
<< (32 - (shift
+ len
)) >> 24;
1739 pixel
|= (pixel
>> len
);
1746 static DWORD
PutField (DWORD pixel
, int shift
, int len
)
1748 shift
= shift
- (8 - len
);
1750 pixel
&= (((1 << len
) - 1) << (8 - len
));
1758 static void SmoothGlyphGray(XImage
*image
, int x
, int y
, void *bitmap
, XGlyphInfo
*gi
,
1764 BYTE
*maskLine
, *mask
, m
;
1769 BYTE src_r
, src_g
, src_b
;
1774 height
= gi
->height
;
1777 maskStride
= (width
+ 3) & ~3;
1779 ExamineBitfield (image
->red_mask
, &r_shift
, &r_len
);
1780 ExamineBitfield (image
->green_mask
, &g_shift
, &g_len
);
1781 ExamineBitfield (image
->blue_mask
, &b_shift
, &b_len
);
1783 src_r
= GetField(color
, r_shift
, r_len
);
1784 src_g
= GetField(color
, g_shift
, g_len
);
1785 src_b
= GetField(color
, b_shift
, b_len
);
1787 for(; height
--; y
++)
1790 maskLine
+= maskStride
;
1795 if(y
>= image
->height
) break;
1799 if(tx
>= image
->width
) break;
1802 if(tx
< 0) continue;
1805 XPutPixel (image
, tx
, y
, color
);
1810 pixel
= XGetPixel (image
, tx
, y
);
1812 r
= GetField(pixel
, r_shift
, r_len
);
1813 r
= ((BYTE
)~m
* (WORD
)r
+ (BYTE
)m
* (WORD
)src_r
) >> 8;
1814 g
= GetField(pixel
, g_shift
, g_len
);
1815 g
= ((BYTE
)~m
* (WORD
)g
+ (BYTE
)m
* (WORD
)src_g
) >> 8;
1816 b
= GetField(pixel
, b_shift
, b_len
);
1817 b
= ((BYTE
)~m
* (WORD
)b
+ (BYTE
)m
* (WORD
)src_b
) >> 8;
1819 pixel
= (PutField (r
, r_shift
, r_len
) |
1820 PutField (g
, g_shift
, g_len
) |
1821 PutField (b
, b_shift
, b_len
));
1822 XPutPixel (image
, tx
, y
, pixel
);
1828 /*************************************************************
1831 * Returns an appropriate Picture for tiling the text colour.
1832 * Call and use result within the xrender_cs
1834 static Picture
get_tile_pict( enum wxr_format wxr_format
, const XRenderColor
*color
)
1840 XRenderColor current_color
;
1841 } tiles
[WXR_NB_FORMATS
], *tile
;
1843 tile
= &tiles
[wxr_format
];
1847 XRenderPictureAttributes pa
;
1848 XRenderPictFormat
*pict_format
= pict_formats
[wxr_format
];
1851 tile
->xpm
= XCreatePixmap(gdi_display
, root_window
, 1, 1, pict_format
->depth
);
1853 pa
.repeat
= RepeatNormal
;
1854 tile
->pict
= pXRenderCreatePicture(gdi_display
, tile
->xpm
, pict_format
, CPRepeat
, &pa
);
1855 wine_tsx11_unlock();
1857 /* init current_color to something different from text_pixel */
1858 tile
->current_color
= *color
;
1859 tile
->current_color
.red
^= 0xffff;
1861 if (wxr_format
== WXR_FORMAT_MONO
)
1863 /* for a 1bpp bitmap we always need a 1 in the tile */
1865 col
.red
= col
.green
= col
.blue
= 0;
1868 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, &col
, 0, 0, 1, 1);
1869 wine_tsx11_unlock();
1873 if (memcmp( color
, &tile
->current_color
, sizeof(*color
) ) && wxr_format
!= WXR_FORMAT_MONO
)
1876 pXRenderFillRectangle(gdi_display
, PictOpSrc
, tile
->pict
, color
, 0, 0, 1, 1);
1877 wine_tsx11_unlock();
1878 tile
->current_color
= *color
;
1883 /*************************************************************
1886 * Returns an appropriate Picture for masking with the specified alpha.
1887 * Call and use result within the xrender_cs
1889 static Picture
get_mask_pict( int alpha
)
1891 static Pixmap pixmap
;
1892 static Picture pict
;
1893 static int current_alpha
;
1895 if (alpha
== 0xffff) return 0; /* don't need a mask for alpha==1.0 */
1899 XRenderPictureAttributes pa
;
1902 pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, 32 );
1903 pa
.repeat
= RepeatNormal
;
1904 pict
= pXRenderCreatePicture( gdi_display
, pixmap
,
1905 pict_formats
[WXR_FORMAT_A8R8G8B8
], CPRepeat
, &pa
);
1906 wine_tsx11_unlock();
1910 if (alpha
!= current_alpha
)
1913 col
.red
= col
.green
= col
.blue
= 0;
1914 col
.alpha
= current_alpha
= alpha
;
1916 pXRenderFillRectangle( gdi_display
, PictOpSrc
, pict
, &col
, 0, 0, 1, 1 );
1917 wine_tsx11_unlock();
1922 static int XRenderErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
1927 /********************************************************************
1928 * is_dib_with_colortable
1930 * Return TRUE if physdev is backed by a dibsection with <= 8 bits per pixel
1932 static inline BOOL
is_dib_with_colortable( X11DRV_PDEVICE
*physDev
)
1936 if( physDev
->bitmap
&& GetObjectW( physDev
->bitmap
->hbitmap
, sizeof(dib
), &dib
) == sizeof(dib
) &&
1937 dib
.dsBmih
.biBitCount
<= 8 )
1943 /***********************************************************************
1944 * xrenderdrv_ExtTextOut
1946 BOOL
xrenderdrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
,
1947 const RECT
*lprect
, LPCWSTR wstr
, UINT count
, const INT
*lpDx
)
1949 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
1951 gsCacheEntry
*entry
;
1952 gsCacheEntryFormat
*formatEntry
;
1954 int textPixel
, backgroundPixel
;
1955 RGNDATA
*saved_region
= NULL
;
1956 BOOL disable_antialias
= FALSE
;
1957 AA_Type aa_type
= AA_None
;
1959 Picture tile_pict
= 0;
1961 if (!physdev
->x11dev
->has_gdi_font
)
1963 dev
= GET_NEXT_PHYSDEV( dev
, pExtTextOut
);
1964 return dev
->funcs
->pExtTextOut( dev
, x
, y
, flags
, lprect
, wstr
, count
, lpDx
);
1967 if(is_dib_with_colortable( physdev
->x11dev
))
1969 TRACE("Disabling antialiasing\n");
1970 disable_antialias
= TRUE
;
1973 xgcval
.function
= GXcopy
;
1974 xgcval
.background
= physdev
->x11dev
->backgroundPixel
;
1975 xgcval
.fill_style
= FillSolid
;
1977 XChangeGC( gdi_display
, physdev
->x11dev
->gc
, GCFunction
| GCBackground
| GCFillStyle
, &xgcval
);
1978 wine_tsx11_unlock();
1980 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
1982 if(physdev
->x11dev
->depth
== 1) {
1983 if((physdev
->x11dev
->textPixel
& 0xffffff) == 0) {
1985 backgroundPixel
= 1;
1988 backgroundPixel
= 0;
1991 textPixel
= physdev
->x11dev
->textPixel
;
1992 backgroundPixel
= physdev
->x11dev
->backgroundPixel
;
1995 if(flags
& ETO_OPAQUE
)
1998 XSetForeground( gdi_display
, physdev
->x11dev
->gc
, backgroundPixel
);
1999 XFillRectangle( gdi_display
, physdev
->x11dev
->drawable
, physdev
->x11dev
->gc
,
2000 physdev
->x11dev
->dc_rect
.left
+ lprect
->left
, physdev
->x11dev
->dc_rect
.top
+ lprect
->top
,
2001 lprect
->right
- lprect
->left
, lprect
->bottom
- lprect
->top
);
2002 wine_tsx11_unlock();
2011 EnterCriticalSection(&xrender_cs
);
2013 entry
= glyphsetCache
+ physdev
->cache_index
;
2014 if( disable_antialias
== FALSE
)
2015 aa_type
= entry
->aa_default
;
2016 formatEntry
= entry
->format
[aa_type
];
2018 for(idx
= 0; idx
< count
; idx
++) {
2019 if( !formatEntry
) {
2020 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
2021 /* re-evaluate antialias since aa_default may have changed */
2022 if( disable_antialias
== FALSE
)
2023 aa_type
= entry
->aa_default
;
2024 formatEntry
= entry
->format
[aa_type
];
2025 } else if( wstr
[idx
] >= formatEntry
->nrealized
|| formatEntry
->realized
[wstr
[idx
]] == FALSE
) {
2026 UploadGlyph(physdev
, wstr
[idx
], aa_type
);
2031 WARN("could not upload requested glyphs\n");
2032 LeaveCriticalSection(&xrender_cs
);
2036 TRACE("Writing %s at %d,%d\n", debugstr_wn(wstr
,count
),
2037 physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
2039 if(X11DRV_XRender_Installed
)
2041 XGlyphElt16
*elts
= HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16
) * count
);
2042 POINT offset
= {0, 0};
2043 POINT desired
, current
;
2044 int render_op
= PictOpOver
;
2045 Picture pict
= get_xrender_picture( physdev
, 0, (flags
& ETO_CLIPPED
) ? lprect
: NULL
);
2048 /* There's a bug in XRenderCompositeText that ignores the xDst and yDst parameters.
2049 So we pass zeros to the function and move to our starting position using the first
2050 element of the elts array. */
2052 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
;
2053 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
;
2054 current
.x
= current
.y
= 0;
2056 get_xrender_color(physdev
->pict_format
, physdev
->x11dev
->textPixel
, &col
);
2057 tile_pict
= get_tile_pict(physdev
->format
, &col
);
2059 /* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
2061 if((physdev
->format
== WXR_FORMAT_MONO
) && (textPixel
== 0))
2062 render_op
= PictOpOutReverse
; /* This gives us 'black' text */
2064 for(idx
= 0; idx
< count
; idx
++)
2066 elts
[idx
].glyphset
= formatEntry
->glyphset
;
2067 elts
[idx
].chars
= wstr
+ idx
;
2068 elts
[idx
].nchars
= 1;
2069 elts
[idx
].xOff
= desired
.x
- current
.x
;
2070 elts
[idx
].yOff
= desired
.y
- current
.y
;
2072 current
.x
+= (elts
[idx
].xOff
+ formatEntry
->gis
[wstr
[idx
]].xOff
);
2073 current
.y
+= (elts
[idx
].yOff
+ formatEntry
->gis
[wstr
[idx
]].yOff
);
2077 desired
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2078 desired
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2084 offset
.x
+= lpDx
[idx
* 2];
2085 offset
.y
+= lpDx
[idx
* 2 + 1];
2088 offset
.x
+= lpDx
[idx
];
2089 desired
.x
= physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
;
2090 desired
.y
= physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
;
2095 /* Make sure we don't have any transforms set from a previous call */
2096 set_xrender_transformation(pict
, 1, 1, 0, 0);
2097 pXRenderCompositeText16(gdi_display
, render_op
,
2100 formatEntry
->font_format
,
2101 0, 0, 0, 0, elts
, count
);
2102 wine_tsx11_unlock();
2103 HeapFree(GetProcessHeap(), 0, elts
);
2105 POINT offset
= {0, 0};
2107 if (flags
& ETO_CLIPPED
)
2109 HRGN clip_region
= CreateRectRgnIndirect( lprect
);
2110 saved_region
= add_extra_clipping_region( physdev
->x11dev
, clip_region
);
2111 DeleteObject( clip_region
);
2115 XSetForeground( gdi_display
, physdev
->x11dev
->gc
, textPixel
);
2117 if(aa_type
== AA_None
|| physdev
->x11dev
->depth
== 1)
2119 void (* sharp_glyph_fn
)(struct xrender_physdev
*, INT
, INT
, void *, XGlyphInfo
*);
2121 if(aa_type
== AA_None
)
2122 sharp_glyph_fn
= SharpGlyphMono
;
2124 sharp_glyph_fn
= SharpGlyphGray
;
2126 for(idx
= 0; idx
< count
; idx
++) {
2127 sharp_glyph_fn(physdev
,
2128 physdev
->x11dev
->dc_rect
.left
+ x
+ offset
.x
,
2129 physdev
->x11dev
->dc_rect
.top
+ y
+ offset
.y
,
2130 formatEntry
->bitmaps
[wstr
[idx
]],
2131 &formatEntry
->gis
[wstr
[idx
]]);
2136 offset
.x
+= lpDx
[idx
* 2];
2137 offset
.y
+= lpDx
[idx
* 2 + 1];
2140 offset
.x
+= lpDx
[idx
];
2144 offset
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2145 offset
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2150 int image_x
, image_y
, image_off_x
, image_off_y
, image_w
, image_h
;
2151 RECT extents
= {0, 0, 0, 0};
2153 int w
= physdev
->x11dev
->drawable_rect
.right
- physdev
->x11dev
->drawable_rect
.left
;
2154 int h
= physdev
->x11dev
->drawable_rect
.bottom
- physdev
->x11dev
->drawable_rect
.top
;
2156 TRACE("drawable %dx%d\n", w
, h
);
2158 for(idx
= 0; idx
< count
; idx
++) {
2159 if(extents
.left
> cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
)
2160 extents
.left
= cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
;
2161 if(extents
.top
> cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
)
2162 extents
.top
= cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
;
2163 if(extents
.right
< cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
+ formatEntry
->gis
[wstr
[idx
]].width
)
2164 extents
.right
= cur
.x
- formatEntry
->gis
[wstr
[idx
]].x
+ formatEntry
->gis
[wstr
[idx
]].width
;
2165 if(extents
.bottom
< cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
+ formatEntry
->gis
[wstr
[idx
]].height
)
2166 extents
.bottom
= cur
.y
- formatEntry
->gis
[wstr
[idx
]].y
+ formatEntry
->gis
[wstr
[idx
]].height
;
2172 cur
.x
+= lpDx
[idx
* 2];
2173 cur
.y
+= lpDx
[idx
* 2 + 1];
2180 cur
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2181 cur
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2184 TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents
.left
, extents
.top
,
2185 extents
.right
, extents
.bottom
, physdev
->x11dev
->dc_rect
.left
+ x
, physdev
->x11dev
->dc_rect
.top
+ y
);
2187 if(physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
>= 0) {
2188 image_x
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
;
2192 image_off_x
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.left
;
2194 if(physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
>= 0) {
2195 image_y
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
;
2199 image_off_y
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.top
;
2201 if(physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.right
< w
)
2202 image_w
= physdev
->x11dev
->dc_rect
.left
+ x
+ extents
.right
- image_x
;
2204 image_w
= w
- image_x
;
2205 if(physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.bottom
< h
)
2206 image_h
= physdev
->x11dev
->dc_rect
.top
+ y
+ extents
.bottom
- image_y
;
2208 image_h
= h
- image_y
;
2210 if(image_w
<= 0 || image_h
<= 0) goto no_image
;
2212 X11DRV_expect_error(gdi_display
, XRenderErrorHandler
, NULL
);
2213 image
= XGetImage(gdi_display
, physdev
->x11dev
->drawable
,
2214 image_x
, image_y
, image_w
, image_h
,
2215 AllPlanes
, ZPixmap
);
2216 X11DRV_check_error();
2218 TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
2219 gdi_display
, (int)physdev
->x11dev
->drawable
, image_x
, image_y
,
2220 image_w
, image_h
, AllPlanes
, ZPixmap
,
2221 physdev
->x11dev
->depth
, image
);
2223 Pixmap xpm
= XCreatePixmap(gdi_display
, root_window
, image_w
, image_h
,
2224 physdev
->x11dev
->depth
);
2228 gcv
.graphics_exposures
= False
;
2229 gc
= XCreateGC(gdi_display
, xpm
, GCGraphicsExposures
, &gcv
);
2230 XCopyArea(gdi_display
, physdev
->x11dev
->drawable
, xpm
, gc
, image_x
, image_y
,
2231 image_w
, image_h
, 0, 0);
2232 XFreeGC(gdi_display
, gc
);
2233 X11DRV_expect_error(gdi_display
, XRenderErrorHandler
, NULL
);
2234 image
= XGetImage(gdi_display
, xpm
, 0, 0, image_w
, image_h
, AllPlanes
,
2236 X11DRV_check_error();
2237 XFreePixmap(gdi_display
, xpm
);
2239 if(!image
) goto no_image
;
2241 image
->red_mask
= visual
->red_mask
;
2242 image
->green_mask
= visual
->green_mask
;
2243 image
->blue_mask
= visual
->blue_mask
;
2245 for(idx
= 0; idx
< count
; idx
++) {
2246 SmoothGlyphGray(image
,
2247 offset
.x
+ image_off_x
- extents
.left
,
2248 offset
.y
+ image_off_y
- extents
.top
,
2249 formatEntry
->bitmaps
[wstr
[idx
]],
2250 &formatEntry
->gis
[wstr
[idx
]],
2251 physdev
->x11dev
->textPixel
);
2256 offset
.x
+= lpDx
[idx
* 2];
2257 offset
.y
+= lpDx
[idx
* 2 + 1];
2260 offset
.x
+= lpDx
[idx
];
2264 offset
.x
+= formatEntry
->gis
[wstr
[idx
]].xOff
;
2265 offset
.y
+= formatEntry
->gis
[wstr
[idx
]].yOff
;
2268 XPutImage(gdi_display
, physdev
->x11dev
->drawable
, physdev
->x11dev
->gc
, image
, 0, 0,
2269 image_x
, image_y
, image_w
, image_h
);
2270 XDestroyImage(image
);
2273 wine_tsx11_unlock();
2274 restore_clipping_region( physdev
->x11dev
, saved_region
);
2276 LeaveCriticalSection(&xrender_cs
);
2280 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2284 /* multiply the alpha channel of a picture */
2285 static void multiply_alpha( Picture pict
, XRenderPictFormat
*format
, int alpha
,
2286 int x
, int y
, int width
, int height
)
2288 XRenderPictureAttributes pa
;
2289 Pixmap src_pixmap
, mask_pixmap
;
2290 Picture src_pict
, mask_pict
;
2294 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
2295 mask_pixmap
= XCreatePixmap( gdi_display
, root_window
, 1, 1, format
->depth
);
2296 pa
.repeat
= RepeatNormal
;
2297 src_pict
= pXRenderCreatePicture( gdi_display
, src_pixmap
, format
, CPRepeat
, &pa
);
2298 pa
.component_alpha
= True
;
2299 mask_pict
= pXRenderCreatePicture( gdi_display
, mask_pixmap
, format
, CPRepeat
|CPComponentAlpha
, &pa
);
2300 color
.red
= color
.green
= color
.blue
= color
.alpha
= 0xffff;
2301 pXRenderFillRectangle( gdi_display
, PictOpSrc
, src_pict
, &color
, 0, 0, 1, 1 );
2302 color
.alpha
= alpha
;
2303 pXRenderFillRectangle( gdi_display
, PictOpSrc
, mask_pict
, &color
, 0, 0, 1, 1 );
2304 pXRenderComposite( gdi_display
, PictOpInReverse
, src_pict
, mask_pict
, pict
,
2305 0, 0, 0, 0, x
, y
, width
, height
);
2306 pXRenderFreePicture( gdi_display
, src_pict
);
2307 pXRenderFreePicture( gdi_display
, mask_pict
);
2308 XFreePixmap( gdi_display
, src_pixmap
);
2309 XFreePixmap( gdi_display
, mask_pixmap
);
2310 wine_tsx11_unlock();
2313 /* Helper function for (stretched) blitting using xrender */
2314 static void xrender_blit( int op
, Picture src_pict
, Picture mask_pict
, Picture dst_pict
,
2315 int x_src
, int y_src
, int x_dst
, int y_dst
,
2316 double xscale
, double yscale
, int width
, int height
)
2318 int x_offset
, y_offset
;
2320 /* When we need to scale we perform scaling and source_x / source_y translation using a transformation matrix.
2321 * This is needed because XRender is inaccurate in combination with scaled source coordinates passed to XRenderComposite.
2322 * In all other cases we do use XRenderComposite for translation as it is faster than using a transformation matrix. */
2324 if(xscale
!= 1.0 || yscale
!= 1.0)
2326 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2327 * in the wrong quadrant of the x-y plane.
2329 x_offset
= (xscale
< 0) ? -width
: 0;
2330 y_offset
= (yscale
< 0) ? -height
: 0;
2331 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
2337 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
2339 pXRenderComposite( gdi_display
, op
, src_pict
, mask_pict
, dst_pict
,
2340 x_offset
, y_offset
, 0, 0, x_dst
, y_dst
, width
, height
);
2341 wine_tsx11_unlock();
2344 /* Helper function for (stretched) mono->color blitting using xrender */
2345 static void xrender_mono_blit( Picture src_pict
, Picture dst_pict
,
2346 enum wxr_format dst_format
, XRenderColor
*fg
, XRenderColor
*bg
,
2347 int x_src
, int y_src
, int x_dst
, int y_dst
,
2348 double xscale
, double yscale
, int width
, int height
)
2351 int x_offset
, y_offset
;
2354 /* When doing a mono->color blit, the source data is used as mask, and the source picture
2355 * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to
2358 EnterCriticalSection( &xrender_cs
);
2360 color
.alpha
= 0xffff; /* tile pict needs 100% alpha */
2361 tile_pict
= get_tile_pict( dst_format
, &color
);
2364 pXRenderFillRectangle( gdi_display
, PictOpSrc
, dst_pict
, fg
, x_dst
, y_dst
, width
, height
);
2366 if (xscale
!= 1.0 || yscale
!= 1.0)
2368 /* In case of mirroring we need a source x- and y-offset because without the pixels will be
2369 * in the wrong quadrant of the x-y plane.
2371 x_offset
= (xscale
< 0) ? -width
: 0;
2372 y_offset
= (yscale
< 0) ? -height
: 0;
2373 set_xrender_transformation(src_pict
, xscale
, yscale
, x_src
, y_src
);
2379 set_xrender_transformation(src_pict
, 1, 1, 0, 0);
2381 pXRenderComposite(gdi_display
, PictOpOver
, tile_pict
, src_pict
, dst_pict
,
2382 0, 0, x_offset
, y_offset
, x_dst
, y_dst
, width
, height
);
2383 wine_tsx11_unlock();
2384 LeaveCriticalSection( &xrender_cs
);
2386 /* force the alpha channel for background pixels, it has been set to 100% by the tile */
2387 if (bg
->alpha
!= 0xffff && (dst_format
== WXR_FORMAT_A8R8G8B8
|| dst_format
== WXR_FORMAT_B8G8R8A8
))
2388 multiply_alpha( dst_pict
, pict_formats
[dst_format
], bg
->alpha
, x_dst
, y_dst
, width
, height
);
2391 static void get_colors( struct xrender_physdev
*physdev_src
, struct xrender_physdev
*physdev_dst
,
2392 XRenderColor
*fg
, XRenderColor
*bg
)
2394 if (physdev_src
->format
== WXR_FORMAT_MONO
)
2399 if (GetDIBColorTable( physdev_src
->dev
.hdc
, 0, 2, rgb
) == 2)
2401 pixel
= X11DRV_PALETTE_ToPhysical( physdev_dst
->x11dev
,
2402 RGB( rgb
[0].rgbRed
, rgb
[0].rgbGreen
, rgb
[0].rgbBlue
));
2403 get_xrender_color( physdev_dst
->pict_format
, pixel
, fg
);
2404 pixel
= X11DRV_PALETTE_ToPhysical( physdev_dst
->x11dev
,
2405 RGB( rgb
[1].rgbRed
, rgb
[1].rgbGreen
, rgb
[1].rgbBlue
));
2406 get_xrender_color( physdev_dst
->pict_format
, pixel
, bg
);
2410 get_xrender_color( physdev_dst
->pict_format
, physdev_dst
->x11dev
->textPixel
, fg
);
2411 get_xrender_color( physdev_dst
->pict_format
, physdev_dst
->x11dev
->backgroundPixel
, bg
);
2414 /* create a pixmap and render picture for an image */
2415 static DWORD
create_image_pixmap( BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2416 struct bitblt_coords
*src
, enum wxr_format format
,
2417 Pixmap
*pixmap
, Picture
*pict
, BOOL
*use_repeat
)
2420 int width
= src
->visrect
.right
- src
->visrect
.left
;
2421 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2422 int depth
= pict_formats
[format
]->depth
;
2423 struct gdi_image_bits dst_bits
;
2424 XRenderPictureAttributes pa
;
2428 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
2429 info
->bmiHeader
.biWidth
, height
, 32, 0 );
2430 wine_tsx11_unlock();
2431 if (!image
) return ERROR_OUTOFMEMORY
;
2433 ret
= copy_image_bits( info
, (format
== WXR_FORMAT_R8G8B8
), image
, bits
, &dst_bits
, src
, NULL
, ~0u );
2434 if (ret
) return ret
;
2436 image
->data
= dst_bits
.ptr
;
2437 /* hack: make sure the bits are readable if we are reading from a DIB section */
2438 /* to be removed once we get rid of DIB access protections */
2439 if (!dst_bits
.is_copy
) IsBadReadPtr( dst_bits
.ptr
, image
->height
* image
->bytes_per_line
);
2441 *use_repeat
= (width
== 1 && height
== 1);
2442 pa
.repeat
= *use_repeat
? RepeatNormal
: RepeatNone
;
2445 *pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
2446 XPutImage( gdi_display
, *pixmap
, get_bitmap_gc( depth
), image
,
2447 src
->visrect
.left
, 0, 0, 0, width
, height
);
2448 *pict
= pXRenderCreatePicture( gdi_display
, *pixmap
, pict_formats
[format
], CPRepeat
, &pa
);
2449 wine_tsx11_unlock();
2451 /* make coordinates relative to the pixmap */
2452 src
->x
-= src
->visrect
.left
;
2453 src
->y
-= src
->visrect
.top
;
2454 OffsetRect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
2458 XDestroyImage( image
);
2459 wine_tsx11_unlock();
2460 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
2464 static void xrender_stretch_blit( struct xrender_physdev
*physdev_src
, struct xrender_physdev
*physdev_dst
,
2465 Drawable drawable
, const struct bitblt_coords
*src
,
2466 const struct bitblt_coords
*dst
)
2468 int width
= abs( dst
->width
);
2469 int height
= abs( dst
->height
);
2470 int x_src
= physdev_src
->x11dev
->dc_rect
.left
+ src
->x
;
2471 int y_src
= physdev_src
->x11dev
->dc_rect
.top
+ src
->y
;
2473 Picture src_pict
= 0, dst_pict
, mask_pict
= 0;
2475 double xscale
, yscale
;
2477 use_repeat
= use_source_repeat( physdev_src
);
2480 xscale
= src
->width
/ (double)dst
->width
;
2481 yscale
= src
->height
/ (double)dst
->height
;
2483 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2485 if (drawable
) /* using an intermediate pixmap */
2487 XRenderPictureAttributes pa
;
2491 pa
.repeat
= RepeatNone
;
2493 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, physdev_dst
->pict_format
, CPRepeat
, &pa
);
2494 wine_tsx11_unlock();
2498 x_dst
= physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
;
2499 y_dst
= physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
;
2500 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2503 if (src
->width
< 0) x_src
+= src
->width
+ 1;
2504 if (src
->height
< 0) y_src
+= src
->height
+ 1;
2505 if (dst
->width
< 0) x_dst
+= dst
->width
+ 1;
2506 if (dst
->height
< 0) y_dst
+= dst
->height
+ 1;
2508 src_pict
= get_xrender_picture_source( physdev_src
, use_repeat
);
2511 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2513 XRenderColor fg
, bg
;
2515 get_colors( physdev_src
, physdev_dst
, &fg
, &bg
);
2516 fg
.alpha
= bg
.alpha
= 0;
2518 xrender_mono_blit( src_pict
, dst_pict
, physdev_dst
->format
, &fg
, &bg
,
2519 x_src
, y_src
, x_dst
, y_dst
, xscale
, yscale
, width
, height
);
2521 else /* color -> color (can be at different depths) or mono -> mono */
2523 if (physdev_dst
->x11dev
->depth
== 32 && physdev_src
->x11dev
->depth
< 32)
2524 mask_pict
= get_no_alpha_mask();
2526 xrender_blit( PictOpSrc
, src_pict
, mask_pict
, dst_pict
,
2527 x_src
, y_src
, x_dst
, y_dst
, xscale
, yscale
, width
, height
);
2533 pXRenderFreePicture( gdi_display
, dst_pict
);
2534 wine_tsx11_unlock();
2539 static void xrender_put_image( Pixmap src_pixmap
, Picture src_pict
, HRGN clip
,
2540 XRenderPictFormat
*dst_format
, struct xrender_physdev
*physdev
,
2541 Drawable drawable
, struct bitblt_coords
*src
,
2542 struct bitblt_coords
*dst
, BOOL use_repeat
)
2544 int x_src
, y_src
, x_dst
, y_dst
;
2546 XRenderPictureAttributes pa
;
2547 double xscale
, yscale
;
2549 if (drawable
) /* using an intermediate pixmap */
2551 RGNDATA
*clip_data
= NULL
;
2553 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
2556 pa
.repeat
= RepeatNone
;
2558 dst_pict
= pXRenderCreatePicture( gdi_display
, drawable
, dst_format
, CPRepeat
, &pa
);
2560 pXRenderSetPictureClipRectangles( gdi_display
, dst_pict
, 0, 0,
2561 (XRectangle
*)clip_data
->Buffer
, clip_data
->rdh
.nCount
);
2562 wine_tsx11_unlock();
2563 HeapFree( GetProcessHeap(), 0, clip_data
);
2567 x_dst
= physdev
->x11dev
->dc_rect
.left
+ dst
->x
;
2568 y_dst
= physdev
->x11dev
->dc_rect
.top
+ dst
->y
;
2569 dst_pict
= get_xrender_picture( physdev
, clip
, &dst
->visrect
);
2574 xscale
= src
->width
/ (double)dst
->width
;
2575 yscale
= src
->height
/ (double)dst
->height
;
2577 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2581 if (src
->width
< 0) x_src
+= src
->width
+ 1;
2582 if (src
->height
< 0) y_src
+= src
->height
+ 1;
2583 if (dst
->width
< 0) x_dst
+= dst
->width
+ 1;
2584 if (dst
->height
< 0) y_dst
+= dst
->height
+ 1;
2586 xrender_blit( PictOpSrc
, src_pict
, 0, dst_pict
, x_src
, y_src
, x_dst
, y_dst
,
2587 xscale
, yscale
, abs( dst
->width
), abs( dst
->height
));
2592 pXRenderFreePicture( gdi_display
, dst_pict
);
2593 wine_tsx11_unlock();
2598 /***********************************************************************
2599 * xrenderdrv_StretchBlt
2601 static BOOL
xrenderdrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
2602 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
2604 struct xrender_physdev
*physdev_dst
= get_xrender_dev( dst_dev
);
2605 struct xrender_physdev
*physdev_src
= get_xrender_dev( src_dev
);
2606 BOOL stretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
2608 if (src_dev
->funcs
!= dst_dev
->funcs
)
2610 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
2611 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
2614 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2616 /* XRender is of no use for color -> mono */
2617 if (physdev_dst
->format
== WXR_FORMAT_MONO
&& physdev_src
->format
!= WXR_FORMAT_MONO
)
2618 goto x11drv_fallback
;
2620 /* if not stretching, we only need to handle format conversion */
2621 if (!stretch
&& physdev_dst
->format
== physdev_src
->format
) goto x11drv_fallback
;
2623 X11DRV_LockDIBSection( physdev_dst
->x11dev
, DIB_Status_GdiMod
);
2624 if (physdev_dst
!= physdev_src
) X11DRV_LockDIBSection( physdev_src
->x11dev
, DIB_Status_GdiMod
);
2630 struct bitblt_coords tmp
;
2632 /* make coordinates relative to tmp pixmap */
2634 tmp
.x
-= tmp
.visrect
.left
;
2635 tmp
.y
-= tmp
.visrect
.top
;
2636 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2639 tmpGC
= XCreateGC( gdi_display
, physdev_dst
->x11dev
->drawable
, 0, NULL
);
2640 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
2641 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
2642 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2643 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev_dst
->x11dev
->depth
);
2644 wine_tsx11_unlock();
2646 xrender_stretch_blit( physdev_src
, physdev_dst
, tmp_pixmap
, src
, &tmp
);
2647 execute_rop( physdev_dst
->x11dev
, tmp_pixmap
, tmpGC
, &dst
->visrect
, rop
);
2650 XFreePixmap( gdi_display
, tmp_pixmap
);
2651 XFreeGC( gdi_display
, tmpGC
);
2652 wine_tsx11_unlock();
2654 else xrender_stretch_blit( physdev_src
, physdev_dst
, 0, src
, dst
);
2656 if (physdev_dst
!= physdev_src
) X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2657 X11DRV_UnlockDIBSection( physdev_dst
->x11dev
, TRUE
);
2661 return X11DRV_StretchBlt( &physdev_dst
->x11dev
->dev
, dst
, &physdev_src
->x11dev
->dev
, src
, rop
);
2665 /***********************************************************************
2666 * xrenderdrv_PutImage
2668 static DWORD
xrenderdrv_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
2669 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
2670 struct bitblt_coords
*dst
, DWORD rop
)
2672 struct xrender_physdev
*physdev
;
2673 X_PHYSBITMAP
*bitmap
;
2677 enum wxr_format src_format
, dst_format
;
2678 XRenderPictFormat
*pict_format
;
2683 if (!X11DRV_XRender_Installed
) goto x11drv_fallback
;
2687 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
2689 dst_format
= get_xrender_format_from_color_shifts( bitmap
->depth
, &bitmap
->color_shifts
);
2693 physdev
= get_xrender_dev( dev
);
2695 dst_format
= physdev
->format
;
2698 src_format
= get_xrender_format_from_bitmapinfo( info
, TRUE
);
2699 if (!(pict_format
= pict_formats
[src_format
])) goto update_format
;
2701 /* make sure we can create an image with the same bpp */
2702 if (info
->bmiHeader
.biBitCount
!= pixmap_formats
[pict_format
->depth
]->bits_per_pixel
)
2705 /* mono <-> color conversions not supported */
2706 if ((src_format
!= dst_format
) && (src_format
== WXR_FORMAT_MONO
|| dst_format
== WXR_FORMAT_MONO
))
2707 goto x11drv_fallback
;
2709 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
2711 ret
= create_image_pixmap( info
, bits
, src
, src_format
, &src_pixmap
, &src_pict
, &use_repeat
);
2714 struct bitblt_coords tmp
;
2718 HRGN rgn
= CreateRectRgnIndirect( &dst
->visrect
);
2719 if (clip
) CombineRgn( rgn
, rgn
, clip
, RGN_AND
);
2721 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
2723 xrender_put_image( src_pixmap
, src_pict
, rgn
, pict_formats
[dst_format
],
2724 NULL
, bitmap
->pixmap
, src
, dst
, use_repeat
);
2726 X11DRV_DIB_Unlock( bitmap
, TRUE
);
2727 DeleteObject( rgn
);
2731 X11DRV_LockDIBSection( physdev
->x11dev
, DIB_Status_GdiMod
);
2735 RGNDATA
*clip_data
= NULL
;
2737 /* make coordinates relative to tmp pixmap */
2739 tmp
.x
-= tmp
.visrect
.left
;
2740 tmp
.y
-= tmp
.visrect
.top
;
2741 OffsetRect( &tmp
.visrect
, -tmp
.visrect
.left
, -tmp
.visrect
.top
);
2743 if (clip
) clip_data
= add_extra_clipping_region( physdev
->x11dev
, clip
);
2746 gc
= XCreateGC( gdi_display
, physdev
->x11dev
->drawable
, 0, NULL
);
2747 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
2748 XSetGraphicsExposures( gdi_display
, gc
, False
);
2749 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, tmp
.visrect
.right
- tmp
.visrect
.left
,
2750 tmp
.visrect
.bottom
- tmp
.visrect
.top
, physdev
->x11dev
->depth
);
2751 wine_tsx11_unlock();
2753 xrender_put_image( src_pixmap
, src_pict
, NULL
, physdev
->pict_format
,
2754 NULL
, tmp_pixmap
, src
, &tmp
, use_repeat
);
2755 execute_rop( physdev
->x11dev
, tmp_pixmap
, gc
, &dst
->visrect
, rop
);
2758 XFreePixmap( gdi_display
, tmp_pixmap
);
2759 XFreeGC( gdi_display
, gc
);
2760 wine_tsx11_unlock();
2762 restore_clipping_region( physdev
->x11dev
, clip_data
);
2764 else xrender_put_image( src_pixmap
, src_pict
, clip
,
2765 physdev
->pict_format
, physdev
, 0, src
, dst
, use_repeat
);
2767 X11DRV_UnlockDIBSection( physdev
->x11dev
, TRUE
);
2771 pXRenderFreePicture( gdi_display
, src_pict
);
2772 XFreePixmap( gdi_display
, src_pixmap
);
2773 wine_tsx11_unlock();
2778 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2779 set_color_info( pict_formats
[dst_format
], info
);
2780 return ERROR_BAD_FORMAT
;
2783 if (hbitmap
) return X11DRV_PutImage( dev
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
2784 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
2785 return dev
->funcs
->pPutImage( dev
, hbitmap
, clip
, info
, bits
, src
, dst
, rop
);
2789 /***********************************************************************
2790 * xrenderdrv_BlendImage
2792 static DWORD
xrenderdrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
2793 struct bitblt_coords
*src
, struct bitblt_coords
*dst
,
2794 BLENDFUNCTION func
)
2796 struct xrender_physdev
*physdev
= get_xrender_dev( dev
);
2798 enum wxr_format format
;
2799 XRenderPictFormat
*pict_format
;
2800 Picture dst_pict
, src_pict
, mask_pict
;
2804 if (!X11DRV_XRender_Installed
)
2806 dev
= GET_NEXT_PHYSDEV( dev
, pBlendImage
);
2807 return dev
->funcs
->pBlendImage( dev
, info
, bits
, src
, dst
, func
);
2810 format
= get_xrender_format_from_bitmapinfo( info
, func
.AlphaFormat
& AC_SRC_ALPHA
);
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 (physdev_dst
!= physdev_src
)
2886 int status
= X11DRV_LockDIBSection( physdev_src
->x11dev
, DIB_Status_None
);
2887 if (status
== DIB_Status_AppMod
|| status
== DIB_Status_InSync
)
2889 X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2890 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
2891 return dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, blendfn
);
2893 X11DRV_CoerceDIBSection( physdev_src
->x11dev
, DIB_Status_GdiMod
);
2895 X11DRV_LockDIBSection( physdev_dst
->x11dev
, DIB_Status_GdiMod
);
2897 dst_pict
= get_xrender_picture( physdev_dst
, 0, &dst
->visrect
);
2899 use_repeat
= use_source_repeat( physdev_src
);
2902 xscale
= src
->width
/ (double)dst
->width
;
2903 yscale
= src
->height
/ (double)dst
->height
;
2905 else xscale
= yscale
= 1; /* no scaling needed with a repeating source */
2907 src_pict
= get_xrender_picture_source( physdev_src
, use_repeat
);
2909 if (physdev_src
->format
== WXR_FORMAT_MONO
&& physdev_dst
->format
!= WXR_FORMAT_MONO
)
2911 /* mono -> color blending needs an intermediate color pixmap */
2912 XRenderColor fg
, bg
;
2913 int width
= src
->visrect
.right
- src
->visrect
.left
;
2914 int height
= src
->visrect
.bottom
- src
->visrect
.top
;
2916 /* blending doesn't use the destination DC colors */
2917 fg
.red
= fg
.green
= fg
.blue
= 0;
2918 bg
.red
= bg
.green
= bg
.blue
= 0xffff;
2919 fg
.alpha
= bg
.alpha
= 0xffff;
2922 tmp_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
,
2923 physdev_dst
->pict_format
->depth
);
2924 pa
.repeat
= use_repeat
? RepeatNormal
: RepeatNone
;
2925 tmp_pict
= pXRenderCreatePicture( gdi_display
, tmp_pixmap
, physdev_dst
->pict_format
,
2927 wine_tsx11_unlock();
2929 xrender_mono_blit( src_pict
, tmp_pict
, physdev_dst
->format
, &fg
, &bg
,
2930 src
->visrect
.left
, src
->visrect
.top
, 0, 0, 1, 1, width
, height
);
2932 else if (!(blendfn
.AlphaFormat
& AC_SRC_ALPHA
) && physdev_src
->pict_format
)
2934 /* we need a source picture with no alpha */
2935 enum wxr_format format
= get_format_without_alpha( physdev_src
->format
);
2936 if (format
!= physdev_src
->format
)
2939 pa
.subwindow_mode
= IncludeInferiors
;
2940 pa
.repeat
= use_repeat
? RepeatNormal
: RepeatNone
;
2941 tmp_pict
= pXRenderCreatePicture( gdi_display
, physdev_src
->x11dev
->drawable
,
2942 pict_formats
[format
], CPSubwindowMode
|CPRepeat
, &pa
);
2943 wine_tsx11_unlock();
2947 if (tmp_pict
) src_pict
= tmp_pict
;
2949 EnterCriticalSection( &xrender_cs
);
2950 mask_pict
= get_mask_pict( blendfn
.SourceConstantAlpha
* 257 );
2952 xrender_blit( PictOpOver
, src_pict
, mask_pict
, dst_pict
,
2953 physdev_src
->x11dev
->dc_rect
.left
+ src
->x
,
2954 physdev_src
->x11dev
->dc_rect
.top
+ src
->y
,
2955 physdev_dst
->x11dev
->dc_rect
.left
+ dst
->x
,
2956 physdev_dst
->x11dev
->dc_rect
.top
+ dst
->y
,
2957 xscale
, yscale
, dst
->width
, dst
->height
);
2960 if (tmp_pict
) pXRenderFreePicture( gdi_display
, tmp_pict
);
2961 if (tmp_pixmap
) XFreePixmap( gdi_display
, tmp_pixmap
);
2962 wine_tsx11_unlock();
2964 LeaveCriticalSection( &xrender_cs
);
2965 if (physdev_src
!= physdev_dst
) X11DRV_UnlockDIBSection( physdev_src
->x11dev
, FALSE
);
2966 X11DRV_UnlockDIBSection( physdev_dst
->x11dev
, TRUE
);
2971 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE
*physDev
, X_PHYSBITMAP
*physBitmap
, int width
, int height
)
2973 /* 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 */
2974 int depth
= physBitmap
->depth
== 1 ? 1 : physDev
->depth
;
2975 enum wxr_format src_format
= get_xrender_format_from_color_shifts(physBitmap
->depth
, &physBitmap
->color_shifts
);
2976 enum wxr_format dst_format
= get_xrender_format_from_color_shifts(physDev
->depth
, physDev
->color_shifts
);
2979 physDev
->brush
.pixmap
= XCreatePixmap(gdi_display
, root_window
, width
, height
, depth
);
2981 /* Use XCopyArea when the physBitmap and brush.pixmap have the same format. */
2982 if( (physBitmap
->depth
== 1) || (!X11DRV_XRender_Installed
&& physDev
->depth
== physBitmap
->depth
) ||
2983 (src_format
== dst_format
) )
2985 XCopyArea( gdi_display
, physBitmap
->pixmap
, physDev
->brush
.pixmap
,
2986 get_bitmap_gc(physBitmap
->depth
), 0, 0, width
, height
, 0, 0 );
2988 else /* We need depth conversion */
2990 Picture src_pict
, dst_pict
;
2991 XRenderPictureAttributes pa
;
2992 pa
.subwindow_mode
= IncludeInferiors
;
2993 pa
.repeat
= RepeatNone
;
2995 src_pict
= pXRenderCreatePicture(gdi_display
, physBitmap
->pixmap
,
2996 pict_formats
[src_format
], CPSubwindowMode
|CPRepeat
, &pa
);
2997 dst_pict
= pXRenderCreatePicture(gdi_display
, physDev
->brush
.pixmap
,
2998 pict_formats
[dst_format
], CPSubwindowMode
|CPRepeat
, &pa
);
3000 xrender_blit(PictOpSrc
, src_pict
, 0, dst_pict
, 0, 0, 0, 0, 1.0, 1.0, width
, height
);
3001 pXRenderFreePicture(gdi_display
, src_pict
);
3002 pXRenderFreePicture(gdi_display
, dst_pict
);
3004 wine_tsx11_unlock();
3007 static const struct gdi_dc_funcs xrender_funcs
=
3009 NULL
, /* pAbortDoc */
3010 NULL
, /* pAbortPath */
3011 xrenderdrv_AlphaBlend
, /* pAlphaBlend */
3012 NULL
, /* pAngleArc */
3015 NULL
, /* pBeginPath */
3016 xrenderdrv_BlendImage
, /* pBlendImage */
3017 NULL
, /* pChoosePixelFormat */
3019 NULL
, /* pCloseFigure */
3020 xrenderdrv_CreateBitmap
, /* pCreateBitmap */
3021 xrenderdrv_CreateCompatibleDC
, /* pCreateCompatibleDC */
3022 xrenderdrv_CreateDC
, /* pCreateDC */
3023 NULL
, /* pCreateDIBSection */
3024 xrenderdrv_DeleteBitmap
, /* pDeleteBitmap */
3025 xrenderdrv_DeleteDC
, /* pDeleteDC */
3026 NULL
, /* pDeleteObject */
3027 NULL
, /* pDescribePixelFormat */
3028 NULL
, /* pDeviceCapabilities */
3029 NULL
, /* pEllipse */
3031 NULL
, /* pEndPage */
3032 NULL
, /* pEndPath */
3033 NULL
, /* pEnumDeviceFonts */
3034 NULL
, /* pEnumICMProfiles */
3035 NULL
, /* pExcludeClipRect */
3036 NULL
, /* pExtDeviceMode */
3037 xrenderdrv_ExtEscape
, /* pExtEscape */
3038 NULL
, /* pExtFloodFill */
3039 NULL
, /* pExtSelectClipRgn */
3040 xrenderdrv_ExtTextOut
, /* pExtTextOut */
3041 NULL
, /* pFillPath */
3042 NULL
, /* pFillRgn */
3043 NULL
, /* pFlattenPath */
3044 NULL
, /* pFrameRgn */
3045 NULL
, /* pGdiComment */
3046 NULL
, /* pGetCharWidth */
3047 NULL
, /* pGetDeviceCaps */
3048 NULL
, /* pGetDeviceGammaRamp */
3049 NULL
, /* pGetICMProfile */
3050 xrenderdrv_GetImage
, /* pGetImage */
3051 NULL
, /* pGetNearestColor */
3052 NULL
, /* pGetPixel */
3053 NULL
, /* pGetPixelFormat */
3054 NULL
, /* pGetSystemPaletteEntries */
3055 NULL
, /* pGetTextExtentExPoint */
3056 NULL
, /* pGetTextMetrics */
3057 NULL
, /* pIntersectClipRect */
3058 NULL
, /* pInvertRgn */
3060 NULL
, /* pModifyWorldTransform */
3062 NULL
, /* pOffsetClipRgn */
3063 NULL
, /* pOffsetViewportOrg */
3064 NULL
, /* pOffsetWindowOrg */
3065 NULL
, /* pPaintRgn */
3068 NULL
, /* pPolyBezier */
3069 NULL
, /* pPolyBezierTo */
3070 NULL
, /* pPolyDraw */
3071 NULL
, /* pPolyPolygon */
3072 NULL
, /* pPolyPolyline */
3073 NULL
, /* pPolygon */
3074 NULL
, /* pPolyline */
3075 NULL
, /* pPolylineTo */
3076 xrenderdrv_PutImage
, /* pPutImage */
3077 NULL
, /* pRealizeDefaultPalette */
3078 NULL
, /* pRealizePalette */
3079 NULL
, /* pRectangle */
3080 NULL
, /* pResetDC */
3081 NULL
, /* pRestoreDC */
3082 NULL
, /* pRoundRect */
3084 NULL
, /* pScaleViewportExt */
3085 NULL
, /* pScaleWindowExt */
3086 xrenderdrv_SelectBitmap
, /* pSelectBitmap */
3087 NULL
, /* pSelectBrush */
3088 NULL
, /* pSelectClipPath */
3089 xrenderdrv_SelectFont
, /* pSelectFont */
3090 NULL
, /* pSelectPalette */
3091 NULL
, /* pSelectPen */
3092 NULL
, /* pSetArcDirection */
3093 NULL
, /* pSetBkColor */
3094 NULL
, /* pSetBkMode */
3095 NULL
, /* pSetDCBrushColor */
3096 NULL
, /* pSetDCPenColor */
3097 NULL
, /* pSetDIBColorTable */
3098 NULL
, /* pSetDIBitsToDevice */
3099 xrenderdrv_SetDeviceClipping
, /* pSetDeviceClipping */
3100 NULL
, /* pSetDeviceGammaRamp */
3101 NULL
, /* pSetLayout */
3102 NULL
, /* pSetMapMode */
3103 NULL
, /* pSetMapperFlags */
3104 NULL
, /* pSetPixel */
3105 NULL
, /* pSetPixelFormat */
3106 NULL
, /* pSetPolyFillMode */
3107 NULL
, /* pSetROP2 */
3108 NULL
, /* pSetRelAbs */
3109 NULL
, /* pSetStretchBltMode */
3110 NULL
, /* pSetTextAlign */
3111 NULL
, /* pSetTextCharacterExtra */
3112 NULL
, /* pSetTextColor */
3113 NULL
, /* pSetTextJustification */
3114 NULL
, /* pSetViewportExt */
3115 NULL
, /* pSetViewportOrg */
3116 NULL
, /* pSetWindowExt */
3117 NULL
, /* pSetWindowOrg */
3118 NULL
, /* pSetWorldTransform */
3119 NULL
, /* pStartDoc */
3120 NULL
, /* pStartPage */
3121 xrenderdrv_StretchBlt
, /* pStretchBlt */
3122 NULL
, /* pStretchDIBits */
3123 NULL
, /* pStrokeAndFillPath */
3124 NULL
, /* pStrokePath */
3125 NULL
, /* pSwapBuffers */
3126 NULL
, /* pUnrealizePalette */
3127 NULL
, /* pWidenPath */
3128 /* OpenGL not supported */
3131 #else /* SONAME_LIBXRENDER */
3133 const struct gdi_dc_funcs
*X11DRV_XRender_Init(void)
3135 TRACE("XRender support not compiled in.\n");
3139 void X11DRV_XRender_Finalize(void)
3143 void X11DRV_XRender_CopyBrush(X11DRV_PDEVICE
*physDev
, X_PHYSBITMAP
*physBitmap
, int width
, int height
)
3146 physDev
->brush
.pixmap
= XCreatePixmap(gdi_display
, root_window
, width
, height
, physBitmap
->pixmap_depth
);
3148 XCopyArea( gdi_display
, physBitmap
->pixmap
, physDev
->brush
.pixmap
,
3149 get_bitmap_gc(physBitmap
->pixmap_depth
), 0, 0, width
, height
, 0, 0 );
3150 wine_tsx11_unlock();
3153 BOOL
X11DRV_XRender_SetPhysBitmapDepth(X_PHYSBITMAP
*physBitmap
, int bits_pixel
, const DIBSECTION
*dib
)
3158 #endif /* SONAME_LIBXRENDER */