winex11: Use an offscreen redirected window for child OpenGL rendering.
This commit is contained in:
parent
ebfba49e27
commit
00633e37bc
|
@ -1393,6 +1393,8 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
|
||||||
ERR("Couldn't set format of the window, returning failure\n");
|
ERR("Couldn't set format of the window, returning failure\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
physDev->gl_drawable = X11DRV_get_gl_drawable(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
physDev->current_pf = iPixelFormat;
|
physDev->current_pf = iPixelFormat;
|
||||||
|
@ -1914,10 +1916,32 @@ static void WINAPI X11DRV_wglGetIntegerv(GLenum pname, GLint* params)
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void update_drawable(X11DRV_PDEVICE *physDev)
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
|
||||||
|
if(!physDev->gl_drawable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
w = physDev->dc_rect.right - physDev->dc_rect.left;
|
||||||
|
h = physDev->dc_rect.bottom - physDev->dc_rect.top;
|
||||||
|
|
||||||
|
if(w > 0 && h > 0) {
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void WINAPI X11DRV_wglFinish(void)
|
static void WINAPI X11DRV_wglFinish(void)
|
||||||
{
|
{
|
||||||
wine_tsx11_lock();
|
wine_tsx11_lock();
|
||||||
pglFinish();
|
pglFinish();
|
||||||
|
update_drawable(((Wine_GLContext*)NtCurrentTeb()->glContext)->physDev);
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1925,6 +1949,7 @@ static void WINAPI X11DRV_wglFlush(void)
|
||||||
{
|
{
|
||||||
wine_tsx11_lock();
|
wine_tsx11_lock();
|
||||||
pglFlush();
|
pglFlush();
|
||||||
|
update_drawable(((Wine_GLContext*)NtCurrentTeb()->glContext)->physDev);
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3188,6 +3213,7 @@ BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev)
|
||||||
drawable = get_glxdrawable(physDev);
|
drawable = get_glxdrawable(physDev);
|
||||||
wine_tsx11_lock();
|
wine_tsx11_lock();
|
||||||
pglXSwapBuffers(gdi_display, drawable);
|
pglXSwapBuffers(gdi_display, drawable);
|
||||||
|
update_drawable(physDev);
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
|
|
||||||
/* FPS support */
|
/* FPS support */
|
||||||
|
@ -3249,6 +3275,16 @@ XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
|
||||||
return visual;
|
return visual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id )
|
||||||
|
{
|
||||||
|
WineGLPixelFormat *fmt;
|
||||||
|
|
||||||
|
fmt = ConvertPixelFormatGLXtoWGL(gdi_display, fbconfig_id);
|
||||||
|
if(fmt == NULL)
|
||||||
|
return NULL;
|
||||||
|
return pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig);
|
||||||
|
}
|
||||||
|
|
||||||
#else /* no OpenGL includes */
|
#else /* no OpenGL includes */
|
||||||
|
|
||||||
int pixelformat_from_fbconfig_id(XID fbconfig_id)
|
int pixelformat_from_fbconfig_id(XID fbconfig_id)
|
||||||
|
@ -3405,4 +3441,9 @@ BOOL destroy_glxpixmap(XID glxpixmap)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* defined(HAVE_OPENGL) */
|
#endif /* defined(HAVE_OPENGL) */
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
#include "x11drv.h"
|
#include "x11drv.h"
|
||||||
|
#include "xcomposite.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/server.h"
|
#include "wine/server.h"
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
|
@ -63,6 +64,8 @@ static const char visual_id_prop[] = "__wine_x11_visual_id";
|
||||||
/* for XDG systray icons */
|
/* for XDG systray icons */
|
||||||
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
||||||
|
|
||||||
|
extern int usexcomposite;
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* is_window_managed
|
* is_window_managed
|
||||||
*
|
*
|
||||||
|
@ -172,16 +175,123 @@ void X11DRV_sync_window_style( Display *display, struct x11drv_win_data *data )
|
||||||
*/
|
*/
|
||||||
BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
|
BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
|
||||||
{
|
{
|
||||||
|
Display *display = thread_display();
|
||||||
struct x11drv_win_data *data;
|
struct x11drv_win_data *data;
|
||||||
|
XVisualInfo *vis;
|
||||||
|
Drawable parent;
|
||||||
|
HWND next_hwnd;
|
||||||
|
int w, h;
|
||||||
|
|
||||||
if (!(data = X11DRV_get_win_data(hwnd))) return FALSE;
|
if (!(data = X11DRV_get_win_data(hwnd))) return FALSE;
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
|
||||||
|
vis = visual_from_fbconfig_id(fbconfig_id);
|
||||||
|
if(!vis) return FALSE;
|
||||||
|
|
||||||
|
if(data->whole_window && vis->visualid == XVisualIDFromVisual(visual))
|
||||||
|
{
|
||||||
|
TRACE("Whole window available and visual match, rendering onscreen\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
|
||||||
|
parent = data->whole_window;
|
||||||
|
next_hwnd = hwnd;
|
||||||
|
while(!parent)
|
||||||
|
{
|
||||||
|
next_hwnd = GetAncestor(next_hwnd, GA_PARENT);
|
||||||
|
if(!next_hwnd)
|
||||||
|
{
|
||||||
|
ERR("Could not find parent HWND with a drawable!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
parent = X11DRV_get_whole_window(next_hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
w = data->client_rect.right - data->client_rect.left;
|
||||||
|
h = data->client_rect.bottom - data->client_rect.top;
|
||||||
|
|
||||||
|
if(w <= 0) w = 1;
|
||||||
|
if(h <= 0) h = 1;
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
#ifdef SONAME_LIBXCOMPOSITE
|
||||||
|
if(usexcomposite)
|
||||||
|
{
|
||||||
|
XSetWindowAttributes attrib;
|
||||||
|
|
||||||
|
attrib.override_redirect = True;
|
||||||
|
attrib.colormap = XCreateColormap(display, parent, vis->visual,
|
||||||
|
(vis->class == PseudoColor ||
|
||||||
|
vis->class == GrayScale ||
|
||||||
|
vis->class == DirectColor) ?
|
||||||
|
AllocAll : AllocNone);
|
||||||
|
XInstallColormap(gdi_display, attrib.colormap);
|
||||||
|
|
||||||
|
data->gl_drawable = XCreateWindow(display, parent, -w, 0, w, h, 0,
|
||||||
|
vis->depth, InputOutput, vis->visual,
|
||||||
|
CWColormap | CWOverrideRedirect,
|
||||||
|
&attrib);
|
||||||
|
if(data->gl_drawable)
|
||||||
|
{
|
||||||
|
pXCompositeRedirectWindow(display, data->gl_drawable,
|
||||||
|
CompositeRedirectManual);
|
||||||
|
XMapWindow(display, data->gl_drawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!data->gl_drawable)
|
||||||
|
{
|
||||||
|
ERR("Failed to create drawable for offscreen rendering\n");
|
||||||
|
XFree(vis);
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
XFree(vis);
|
||||||
|
|
||||||
|
XFlush(display);
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
|
||||||
|
TRACE("Created GL drawable 0x%lx, using FBConfigID 0x%lx\n",
|
||||||
|
data->gl_drawable, fbconfig_id);
|
||||||
|
|
||||||
data->fbconfig_id = fbconfig_id;
|
data->fbconfig_id = fbconfig_id;
|
||||||
SetPropA(hwnd, fbconfig_id_prop, (HANDLE)data->fbconfig_id);
|
SetPropA(hwnd, fbconfig_id_prop, (HANDLE)data->fbconfig_id);
|
||||||
|
SetPropA(hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable);
|
||||||
invalidate_dce( hwnd, &data->window_rect );
|
invalidate_dce( hwnd, &data->window_rect );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_gl_drawable(Display *display, struct x11drv_win_data *data, const RECT *old_client_rect)
|
||||||
|
{
|
||||||
|
int w = data->client_rect.right - data->client_rect.left;
|
||||||
|
int h = data->client_rect.bottom - data->client_rect.top;
|
||||||
|
|
||||||
|
if((w == old_client_rect->right - old_client_rect->left &&
|
||||||
|
h == old_client_rect->bottom - old_client_rect->top) ||
|
||||||
|
w <= 0 || h <= 0)
|
||||||
|
{
|
||||||
|
TRACE("No resize needed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Resizing GL drawable 0x%lx to %dx%d\n", data->gl_drawable, w, h);
|
||||||
|
#ifdef SONAME_LIBXCOMPOSITE
|
||||||
|
if(usexcomposite)
|
||||||
|
{
|
||||||
|
wine_tsx11_lock();
|
||||||
|
XMoveResizeWindow(display, data->gl_drawable, -w, 0, w, h);
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* get_window_changes
|
* get_window_changes
|
||||||
|
@ -726,13 +836,18 @@ void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data
|
||||||
XWindowChanges changes;
|
XWindowChanges changes;
|
||||||
int mask;
|
int mask;
|
||||||
RECT old_whole_rect;
|
RECT old_whole_rect;
|
||||||
|
RECT old_client_rect;
|
||||||
|
|
||||||
old_whole_rect = data->whole_rect;
|
old_whole_rect = data->whole_rect;
|
||||||
data->whole_rect = *new_whole_rect;
|
data->whole_rect = *new_whole_rect;
|
||||||
|
|
||||||
|
old_client_rect = data->client_rect;
|
||||||
data->client_rect = *new_client_rect;
|
data->client_rect = *new_client_rect;
|
||||||
OffsetRect( &data->client_rect, -data->whole_rect.left, -data->whole_rect.top );
|
OffsetRect( &data->client_rect, -data->whole_rect.left, -data->whole_rect.top );
|
||||||
|
|
||||||
|
if (data->gl_drawable)
|
||||||
|
update_gl_drawable(display, data, &old_client_rect);
|
||||||
|
|
||||||
if (!data->whole_window || data->lock_changes) return;
|
if (!data->whole_window || data->lock_changes) return;
|
||||||
|
|
||||||
mask = get_window_changes( &changes, &old_whole_rect, &data->whole_rect );
|
mask = get_window_changes( &changes, &old_whole_rect, &data->whole_rect );
|
||||||
|
@ -931,6 +1046,13 @@ void X11DRV_DestroyWindow( HWND hwnd )
|
||||||
|
|
||||||
if (!(data = X11DRV_get_win_data( hwnd ))) return;
|
if (!(data = X11DRV_get_win_data( hwnd ))) return;
|
||||||
|
|
||||||
|
if (data->gl_drawable)
|
||||||
|
{
|
||||||
|
wine_tsx11_lock();
|
||||||
|
XDestroyWindow(display, data->gl_drawable);
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
free_window_dce( data );
|
free_window_dce( data );
|
||||||
destroy_whole_window( display, data );
|
destroy_whole_window( display, data );
|
||||||
destroy_icon_window( display, data );
|
destroy_icon_window( display, data );
|
||||||
|
|
|
@ -669,6 +669,7 @@ extern XIC X11DRV_get_ic( HWND hwnd );
|
||||||
extern BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig );
|
extern BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig );
|
||||||
|
|
||||||
extern int pixelformat_from_fbconfig_id( XID fbconfig_id );
|
extern int pixelformat_from_fbconfig_id( XID fbconfig_id );
|
||||||
|
extern XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id );
|
||||||
|
|
||||||
extern void alloc_window_dce( struct x11drv_win_data *data );
|
extern void alloc_window_dce( struct x11drv_win_data *data );
|
||||||
extern void free_window_dce( struct x11drv_win_data *data );
|
extern void free_window_dce( struct x11drv_win_data *data );
|
||||||
|
|
Loading…
Reference in New Issue