winex11: Get rid of the static Xrender picture format table.

This commit is contained in:
Roderick Colenbrander 2009-07-05 20:35:01 +02:00 committed by Alexandre Julliard
parent 26caf2fdda
commit 8262e0a800
1 changed files with 197 additions and 48 deletions

View File

@ -54,8 +54,57 @@ static BOOL X11DRV_XRender_Installed = FALSE;
#define RepeatReflect 3
#endif
enum drawable_depth_type {mono_drawable, color_drawable};
static XRenderPictFormat *pict_formats[2];
#define MAX_FORMATS 9
typedef enum wine_xrformat
{
WXR_FORMAT_MONO,
WXR_FORMAT_X1R5G5B5,
WXR_FORMAT_X1B5G5R5,
WXR_FORMAT_R5G6B5,
WXR_FORMAT_B5G6R5,
WXR_FORMAT_R8G8B8,
WXR_FORMAT_B8G8R8,
WXR_FORMAT_A8R8G8B8,
WXR_FORMAT_X8R8G8B8,
} WXRFormat;
typedef struct wine_xrender_format_template
{
WXRFormat wxr_format;
unsigned int depth;
unsigned int alpha;
unsigned int alphaMask;
unsigned int red;
unsigned int redMask;
unsigned int green;
unsigned int greenMask;
unsigned int blue;
unsigned int blueMask;
} WineXRenderFormatTemplate;
static const WineXRenderFormatTemplate wxr_formats_template[] =
{
/* Format depth alpha mask red mask green mask blue mask*/
{WXR_FORMAT_MONO, 1, 0, 0x01, 0, 0, 0, 0, 0, 0 },
{WXR_FORMAT_X1R5G5B5, 16, 0, 0, 10, 0x1f, 5, 0x1f, 0, 0x1f },
{WXR_FORMAT_X1B5G5R5, 16, 0, 0, 0, 0x1f, 5, 0x1f, 10, 0x1f },
{WXR_FORMAT_R5G6B5, 16, 0, 0, 11, 0x1f, 5, 0x3f, 0, 0x1f },
{WXR_FORMAT_B5G6R5, 16, 0, 0, 0, 0x1f, 5, 0x3f, 11, 0x1f },
{WXR_FORMAT_R8G8B8, 24, 0, 0, 16, 0xff, 8, 0xff, 0, 0xff },
{WXR_FORMAT_B8G8R8, 24, 0, 0, 0, 0xff, 8, 0xff, 16, 0xff },
{WXR_FORMAT_A8R8G8B8, 32, 24, 0xff, 16, 0xff, 8, 0xff, 0, 0xff },
{WXR_FORMAT_X8R8G8B8, 32, 0, 0, 16, 0xff, 8, 0xff, 0, 0xff }
};
typedef struct wine_xrender_format
{
WXRFormat format;
XRenderPictFormat *pict_format;
} WineXRenderFormat;
static WineXRenderFormat wxr_formats[MAX_FORMATS];
static int WineXRenderFormatsListSize = 0;
static WineXRenderFormat *default_format = NULL;
typedef struct
{
@ -155,6 +204,101 @@ static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
#define NATIVE_BYTE_ORDER LSBFirst
#endif
static BOOL get_xrender_template(const WineXRenderFormatTemplate *fmt, XRenderPictFormat *templ, unsigned long *mask)
{
templ->id = 0;
templ->type = PictTypeDirect;
templ->depth = fmt->depth;
templ->direct.alpha = fmt->alpha;
templ->direct.alphaMask = fmt->alphaMask;
templ->direct.red = fmt->red;
templ->direct.redMask = fmt->redMask;
templ->direct.green = fmt->green;
templ->direct.greenMask = fmt->greenMask;
templ->direct.blue = fmt->blue;
templ->direct.blueMask = fmt->blueMask;
templ->colormap = 0;
*mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask | PictFormatRed | PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | PictFormatBlue | PictFormatBlueMask;
return TRUE;
}
static BOOL is_wxrformat_compatible_with_default_visual(const WineXRenderFormatTemplate *fmt)
{
if(fmt->depth != screen_depth)
return FALSE;
if( (fmt->redMask << fmt->red) != visual->red_mask)
return FALSE;
if( (fmt->greenMask << fmt->green) != visual->green_mask)
return FALSE;
if( (fmt->blueMask << fmt->blue) != visual->blue_mask)
return FALSE;
/* We never select a default ARGB visual */
if(fmt->alphaMask)
return FALSE;
return TRUE;
}
static int load_xrender_formats(void)
{
unsigned int i;
for(i = 0; i < (sizeof(wxr_formats_template) / sizeof(wxr_formats_template[0])); i++)
{
XRenderPictFormat templ, *pict_format;
if(is_wxrformat_compatible_with_default_visual(&wxr_formats_template[i]))
{
wine_tsx11_lock();
pict_format = pXRenderFindVisualFormat(gdi_display, visual);
if(!pict_format)
{
/* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
if (visual->class == DirectColor)
{
XVisualInfo info;
if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
screen_depth, TrueColor, &info ))
{
pict_format = pXRenderFindVisualFormat(gdi_display, info.visual);
if (pict_format) visual = info.visual;
}
}
}
wine_tsx11_unlock();
if(pict_format)
{
wxr_formats[WineXRenderFormatsListSize].format = wxr_formats_template[i].wxr_format;
wxr_formats[WineXRenderFormatsListSize].pict_format = pict_format;
default_format = &wxr_formats[WineXRenderFormatsListSize];
WineXRenderFormatsListSize++;
TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_format->id, wxr_formats_template[i].wxr_format);
}
}
else
{
unsigned long mask = 0;
get_xrender_template(&wxr_formats_template[i], &templ, &mask);
wine_tsx11_lock();
pict_format = pXRenderFindFormat(gdi_display, mask, &templ, 0);
wine_tsx11_unlock();
if(pict_format)
{
wxr_formats[WineXRenderFormatsListSize].format = wxr_formats_template[i].wxr_format;
wxr_formats[WineXRenderFormatsListSize].pict_format = pict_format;
WineXRenderFormatsListSize++;
TRACE("Loaded pict_format with id=%#lx for wxr_format=%#x\n", pict_format->id, wxr_formats_template[i].wxr_format);
}
}
}
return WineXRenderFormatsListSize;
}
/***********************************************************************
* X11DRV_XRender_Init
*
@ -164,7 +308,6 @@ static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
void X11DRV_XRender_Init(void)
{
int event_base, i;
XRenderPictFormat pf;
if (client_side_with_render &&
wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
@ -195,27 +338,12 @@ LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform)
#undef LOAD_OPTIONAL_FUNCPTR
#endif
wine_tsx11_lock();
if(pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base)) {
X11DRV_XRender_Installed = TRUE;
X11DRV_XRender_Installed = pXRenderQueryExtension(gdi_display, &event_base, &xrender_error_base);
wine_tsx11_unlock();
if(X11DRV_XRender_Installed) {
TRACE("Xrender is up and running error_base = %d\n", xrender_error_base);
pict_formats[color_drawable] = pXRenderFindVisualFormat(gdi_display, visual);
if(!pict_formats[color_drawable])
{
/* Xrender doesn't like DirectColor visuals, try to find a TrueColor one instead */
if (visual->class == DirectColor)
{
XVisualInfo info;
if (XMatchVisualInfo( gdi_display, DefaultScreen(gdi_display),
screen_depth, TrueColor, &info ))
{
pict_formats[color_drawable] = pXRenderFindVisualFormat(gdi_display, info.visual);
if (pict_formats[color_drawable]) visual = info.visual;
}
}
}
if(!pict_formats[color_drawable]) /* This fails in buggy versions of libXrender.so */
if(!load_xrender_formats()) /* This fails in buggy versions of libXrender.so */
{
wine_tsx11_unlock();
WINE_MESSAGE(
@ -225,23 +353,12 @@ LOAD_OPTIONAL_FUNCPTR(XRenderSetPictureTransform)
X11DRV_XRender_Installed = FALSE;
return;
}
pf.type = PictTypeDirect;
pf.depth = 1;
pf.direct.alpha = 0;
pf.direct.alphaMask = 1;
pict_formats[mono_drawable] = pXRenderFindFormat(gdi_display, PictFormatType |
PictFormatDepth | PictFormatAlpha |
PictFormatAlphaMask, &pf, 0);
if(!pict_formats[mono_drawable]) {
ERR("mono_format == NULL?\n");
X11DRV_XRender_Installed = FALSE;
}
if (!visual->red_mask || !visual->green_mask || !visual->blue_mask) {
WARN("one or more of the colour masks are 0, disabling XRENDER. Try running in 16-bit mode or higher.\n");
X11DRV_XRender_Installed = FALSE;
}
}
wine_tsx11_unlock();
}
sym_not_found:
@ -271,6 +388,39 @@ sym_not_found:
else TRACE("Using X11 core fonts\n");
}
static WineXRenderFormat *get_xrender_format(WXRFormat format)
{
int i;
for(i=0; i<WineXRenderFormatsListSize; i++)
{
if(wxr_formats[i].format == format)
{
TRACE("Returning wxr_format=%#x\n", format);
return &wxr_formats[i];
}
}
return NULL;
}
static WineXRenderFormat *get_xrender_format_from_pdevice(X11DRV_PDEVICE *physDev)
{
WXRFormat format;
switch(physDev->depth)
{
case 1:
format = WXR_FORMAT_MONO;
break;
default:
/* For now fall back to the format of the default visual.
In the future we should check if we are using a DDB/DIB and what exact format we need.
*/
return default_format;
}
return get_xrender_format(format);
}
static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
{
if(p1->hash != p2->hash) return TRUE;
@ -1153,33 +1303,33 @@ static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInf
* Returns an appropriate Picture for tiling the text colour.
* Call and use result within the xrender_cs
*/
static Picture get_tile_pict(enum drawable_depth_type type, int text_pixel)
static Picture get_tile_pict(WineXRenderFormat *wxr_format, int text_pixel)
{
static struct
{
Pixmap xpm;
Picture pict;
int current_color;
} tiles[2], *tile;
} tiles[MAX_FORMATS], *tile;
XRenderColor col;
tile = &tiles[type];
tile = &tiles[wxr_format->format];
if(!tile->xpm)
{
XRenderPictureAttributes pa;
wine_tsx11_lock();
tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, pict_formats[type]->depth);
tile->xpm = XCreatePixmap(gdi_display, root_window, 1, 1, wxr_format->pict_format->depth);
pa.repeat = RepeatNormal;
tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, pict_formats[type], CPRepeat, &pa);
tile->pict = pXRenderCreatePicture(gdi_display, tile->xpm, wxr_format->pict_format, CPRepeat, &pa);
wine_tsx11_unlock();
/* init current_color to something different from text_pixel */
tile->current_color = ~text_pixel;
if(type == mono_drawable)
if(wxr_format->format == WXR_FORMAT_MONO)
{
/* for a 1bpp bitmap we always need a 1 in the tile */
col.red = col.green = col.blue = 0;
@ -1190,7 +1340,7 @@ static Picture get_tile_pict(enum drawable_depth_type type, int text_pixel)
}
}
if(text_pixel != tile->current_color && type == color_drawable)
if(text_pixel != tile->current_color && wxr_format->format != WXR_FORMAT_MONO)
{
/* Map 0 -- 0xff onto 0 -- 0xffff */
int r_shift, r_len;
@ -1243,7 +1393,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
unsigned int idx;
double cosEsc, sinEsc;
LOGFONTW lf;
enum drawable_depth_type depth_type = (physDev->depth == 1) ? mono_drawable : color_drawable;
WineXRenderFormat *dst_format = get_xrender_format_from_pdevice(physDev);
Picture tile_pict = 0;
/* Do we need to disable antialiasing because of palette mode? */
@ -1322,8 +1472,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
wine_tsx11_lock();
physDev->xrender->pict = pXRenderCreatePicture(gdi_display,
physDev->drawable,
pict_formats[depth_type],
physDev->drawable, dst_format->pict_format,
CPSubwindowMode, &pa);
wine_tsx11_unlock();
@ -1388,11 +1537,11 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
desired.y = physDev->dc_rect.top + y;
current.x = current.y = 0;
tile_pict = get_tile_pict(depth_type, physDev->textPixel);
tile_pict = get_tile_pict(dst_format, physDev->textPixel);
/* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
*/
if((depth_type == mono_drawable) && (textPixel == 0))
if((dst_format->format == WXR_FORMAT_MONO) && (textPixel == 0))
render_op = PictOpOutReverse; /* This gives us 'black' text */
for(idx = 0; idx < count; idx++)
@ -1630,7 +1779,7 @@ BOOL CDECL X11DRV_AlphaBlend(X11DRV_PDEVICE *devDst, INT xDst, INT yDst, INT wid
POINT pts[2];
BOOL top_down = FALSE;
RGNDATA *rgndata;
enum drawable_depth_type dst_depth_type = (devDst->depth == 1) ? mono_drawable : color_drawable;
WineXRenderFormat *dst_format = get_xrender_format_from_pdevice(devDst);
int repeat_src;
if(!X11DRV_XRender_Installed) {
@ -1761,7 +1910,7 @@ BOOL CDECL X11DRV_AlphaBlend(X11DRV_PDEVICE *devDst, INT xDst, INT yDst, INT wid
/* FIXME use devDst->xrender->pict ? */
dst_pict = pXRenderCreatePicture(gdi_display,
devDst->drawable,
pict_formats[dst_depth_type],
dst_format->pict_format,
CPSubwindowMode, &pa);
TRACE("dst_pict %08lx\n", dst_pict);
TRACE("src_drawable = %08lx\n", devSrc->drawable);