winex11: Use a GLXPixmap for offscreen OpenGL rendering when XComposite isn't available.

This commit is contained in:
Chris Robinson 2007-09-26 08:17:13 -07:00 committed by Alexandre Julliard
parent 3629ea4cfd
commit 37d835bf9a
5 changed files with 130 additions and 6 deletions

View File

@ -152,12 +152,14 @@ static void update_visible_region( struct dce *dce )
escape.drawable = data->icon_window;
escape.fbconfig_id = 0;
escape.gl_drawable = 0;
escape.pixmap = 0;
}
else
{
escape.drawable = X11DRV_get_whole_window( top );
escape.fbconfig_id = X11DRV_get_fbconfig_id( dce->hwnd );
escape.gl_drawable = X11DRV_get_gl_drawable( dce->hwnd );
escape.pixmap = X11DRV_get_gl_pixmap( dce->hwnd );
}
escape.code = X11DRV_SET_DRAWABLE;
@ -195,6 +197,7 @@ static void release_dce( struct dce *dce )
virtual_screen_rect.bottom - virtual_screen_rect.top );
escape.fbconfig_id = 0;
escape.gl_drawable = 0;
escape.pixmap = 0;
ExtEscape( dce->hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
}

View File

@ -342,6 +342,7 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *physDev, INT escape, INT in_count, LPCVOID
physDev->drawable_rect = data->drawable_rect;
physDev->current_pf = pixelformat_from_fbconfig_id( data->fbconfig_id );
physDev->gl_drawable = data->gl_drawable;
physDev->pixmap = data->pixmap;
wine_tsx11_lock();
XSetSubwindowMode( gdi_display, physDev->gc, data->mode );
wine_tsx11_unlock();

View File

@ -972,6 +972,12 @@ static inline void sync_context(Wine_GLContext *context)
}
Drawable create_glxpixmap(Display *display, XVisualInfo *vis, Pixmap parent)
{
return pglXCreateGLXPixmap(display, vis, parent);
}
/**
* X11DRV_ChoosePixelFormat
*
@ -1965,12 +1971,14 @@ static inline void update_drawable(X11DRV_PDEVICE *physDev)
h = physDev->dc_rect.bottom - physDev->dc_rect.top;
if(w > 0 && h > 0) {
Drawable src = physDev->pixmap;
if(!src) src = physDev->gl_drawable;
/* The GL drawable may be lagged behind if we don't flush first, so
* flush the display make sure we copy up-to-date data */
XFlush(gdi_display);
XCopyArea(gdi_display, physDev->gl_drawable, physDev->drawable,
physDev->gc, 0, 0, w, h, physDev->dc_rect.left,
physDev->dc_rect.top);
XCopyArea(gdi_display, src, physDev->drawable, physDev->gc, 0, 0, w, h,
physDev->dc_rect.left, physDev->dc_rect.top);
}
}
@ -3189,7 +3197,7 @@ static void X11DRV_WineGL_LoadExtensions(void)
}
static XID create_glxpixmap(X11DRV_PDEVICE *physDev)
static XID create_bitmap_glxpixmap(X11DRV_PDEVICE *physDev)
{
GLXPixmap ret;
XVisualInfo *vis;
@ -3220,7 +3228,7 @@ Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
else
{
if(!physDev->bitmap->glxpixmap)
physDev->bitmap->glxpixmap = create_glxpixmap(physDev);
physDev->bitmap->glxpixmap = create_bitmap_glxpixmap(physDev);
ret = physDev->bitmap->glxpixmap;
}
}
@ -3344,6 +3352,11 @@ void mark_drawable_dirty(Drawable old, Drawable new)
{
}
Drawable create_glxpixmap(Display *display, XVisualInfo *vis, Pixmap parent)
{
return 0;
}
/***********************************************************************
* ChoosePixelFormat (X11DRV.@)
*/

View File

@ -58,6 +58,7 @@ static const char whole_window_prop[] = "__wine_x11_whole_window";
static const char icon_window_prop[] = "__wine_x11_icon_window";
static const char fbconfig_id_prop[] = "__wine_x11_fbconfig_id";
static const char gl_drawable_prop[] = "__wine_x11_gl_drawable";
static const char pixmap_prop[] = "__wine_x11_pixmap";
static const char managed_prop[] = "__wine_x11_managed";
static const char visual_id_prop[] = "__wine_x11_visual_id";
@ -241,7 +242,27 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
XMapWindow(display, data->gl_drawable);
}
}
else
#endif
{
WARN("XComposite is not available, using GLXPixmap hack\n");
data->pixmap = XCreatePixmap(display, parent, w, h, vis->depth);
if(!data->pixmap)
{
ERR("Failed to create pixmap for offscreen rendering\n");
XFree(vis);
wine_tsx11_unlock();
return FALSE;
}
data->gl_drawable = create_glxpixmap(display, vis, data->pixmap);
if(!data->gl_drawable)
{
XFreePixmap(display, data->pixmap);
data->pixmap = 0;
}
}
if(!data->gl_drawable)
{
@ -263,6 +284,7 @@ done:
data->fbconfig_id = fbconfig_id;
SetPropA(hwnd, fbconfig_id_prop, (HANDLE)data->fbconfig_id);
SetPropA(hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable);
SetPropA(hwnd, pixmap_prop, (HANDLE)data->pixmap);
invalidate_dce( hwnd, &data->window_rect );
return TRUE;
}
@ -271,6 +293,11 @@ static void update_gl_drawable(Display *display, struct x11drv_win_data *data, c
{
int w = data->client_rect.right - data->client_rect.left;
int h = data->client_rect.bottom - data->client_rect.top;
XVisualInfo *vis;
Drawable parent;
HWND next_hwnd;
Drawable glxp;
Pixmap pix;
if((w == old_client_rect->right - old_client_rect->left &&
h == old_client_rect->bottom - old_client_rect->top) ||
@ -290,6 +317,60 @@ static void update_gl_drawable(Display *display, struct x11drv_win_data *data, c
return;
}
#endif
parent = data->whole_window;
next_hwnd = data->hwnd;
while(!parent)
{
next_hwnd = GetAncestor(next_hwnd, GA_PARENT);
if(!next_hwnd)
{
ERR("Could not find parent HWND with a drawable!\n");
return;
}
parent = X11DRV_get_whole_window(next_hwnd);
}
wine_tsx11_lock();
vis = visual_from_fbconfig_id(data->fbconfig_id);
if(!vis) return;
pix = XCreatePixmap(display, parent, w, h, vis->depth);
if(!pix)
{
ERR("Failed to create pixmap for offscreen rendering\n");
XFree(vis);
wine_tsx11_unlock();
return;
}
glxp = create_glxpixmap(display, vis, pix);
if(!glxp)
{
ERR("Failed to create drawable for offscreen rendering\n");
XFreePixmap(display, pix);
XFree(vis);
wine_tsx11_unlock();
return;
}
XFree(vis);
mark_drawable_dirty(data->gl_drawable, glxp);
XFreePixmap(display, data->pixmap);
destroy_glxpixmap(display, data->gl_drawable);
data->pixmap = pix;
data->gl_drawable = glxp;
XFlush(display);
wine_tsx11_unlock();
SetPropA(data->hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable);
SetPropA(data->hwnd, pixmap_prop, (HANDLE)data->pixmap);
invalidate_dce( data->hwnd, &data->window_rect );
}
@ -1046,7 +1127,14 @@ void X11DRV_DestroyWindow( HWND hwnd )
if (!(data = X11DRV_get_win_data( hwnd ))) return;
if (data->gl_drawable)
if (data->pixmap)
{
destroy_glxpixmap(display, data->gl_drawable);
wine_tsx11_lock();
XFreePixmap(display, data->pixmap);
wine_tsx11_unlock();
}
else if (data->gl_drawable)
{
wine_tsx11_lock();
XDestroyWindow(display, data->gl_drawable);
@ -1079,6 +1167,7 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd )
data->icon_window = 0;
data->fbconfig_id = 0;
data->gl_drawable = 0;
data->pixmap = 0;
data->xic = 0;
data->managed = FALSE;
data->dce = NULL;
@ -1397,6 +1486,19 @@ Drawable X11DRV_get_gl_drawable( HWND hwnd )
return data->gl_drawable;
}
/***********************************************************************
* X11DRV_get_gl_pixmap
*
* Return the Pixmap associated with the GL drawable (if any) for this window.
*/
Pixmap X11DRV_get_gl_pixmap( HWND hwnd )
{
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
if (!data) return (Pixmap)GetPropA( hwnd, pixmap_prop );
return data->pixmap;
}
/***********************************************************************
* X11DRV_get_ic

View File

@ -140,6 +140,7 @@ typedef struct
struct dce *dce; /* opaque pointer to DCE */
int current_pf;
Drawable gl_drawable;
Pixmap pixmap; /* Pixmap for a GLXPixmap gl_drawable */
XRENDERINFO xrender;
} X11DRV_PDEVICE;
@ -488,6 +489,7 @@ struct x11drv_escape_set_drawable
RECT drawable_rect;/* Drawable rectangle relative to screen */
XID fbconfig_id; /* fbconfig id used by the GL drawable */
Drawable gl_drawable; /* GL drawable */
Pixmap pixmap; /* Pixmap for a GLXPixmap gl_drawable */
};
struct x11drv_escape_set_dce
@ -648,6 +650,7 @@ struct x11drv_win_data
Window icon_window; /* X window for the icon */
XID fbconfig_id; /* fbconfig id for the GL drawable this hwnd uses */
Drawable gl_drawable; /* Optional GL drawable for rendering the client area */
Pixmap pixmap; /* Base pixmap for if gl_drawable is a GLXPixmap */
RECT window_rect; /* USER window rectangle relative to parent */
RECT whole_rect; /* X window rectangle for the whole window relative to parent */
RECT client_rect; /* client area relative to whole window */
@ -664,6 +667,7 @@ extern struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd );
extern Window X11DRV_get_whole_window( HWND hwnd );
extern XID X11DRV_get_fbconfig_id( HWND hwnd );
extern Drawable X11DRV_get_gl_drawable( HWND hwnd );
extern Pixmap X11DRV_get_gl_pixmap( HWND hwnd );
extern BOOL X11DRV_is_window_rect_mapped( const RECT *rect );
extern XIC X11DRV_get_ic( HWND hwnd );
extern BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig );
@ -671,6 +675,7 @@ extern BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig );
extern int pixelformat_from_fbconfig_id( XID fbconfig_id );
extern XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id );
extern void mark_drawable_dirty( Drawable old, Drawable new );
extern Drawable create_glxpixmap( Display *display, XVisualInfo *vis, Pixmap parent );
extern void alloc_window_dce( struct x11drv_win_data *data );
extern void free_window_dce( struct x11drv_win_data *data );