Commit ac4f2ac3 authored by Alexandre Julliard's avatar Alexandre Julliard

winex11: Hold a reference to the drawable from the GL context.

parent 6dc30a2e
......@@ -217,7 +217,8 @@ struct wgl_context
int numAttribs; /* This is needed for delaying wglCreateContextAttribsARB */
int attribList[16]; /* This is needed for delaying wglCreateContextAttribsARB */
GLXContext ctx;
GLXDrawable drawables[2];
struct gl_drawable *drawables[2];
struct gl_drawable *new_drawables[2];
BOOL refresh_drawables;
struct list entry;
};
......@@ -1228,12 +1229,15 @@ static void release_gl_drawable( struct gl_drawable *gl )
if (InterlockedDecrement( &gl->ref )) return;
switch (gl->type)
{
case DC_GL_WINDOW:
case DC_GL_CHILD_WIN:
TRACE( "destroying %lx drawable %lx\n", gl->window, gl->drawable );
pglXDestroyWindow( gdi_display, gl->drawable );
XDestroyWindow( gdi_display, gl->window );
XFreeColormap( gdi_display, gl->colormap );
if (gl->colormap) XFreeColormap( gdi_display, gl->colormap );
break;
case DC_GL_PIXMAP_WIN:
TRACE( "destroying pixmap %lx drawable %lx\n", gl->pixmap, gl->drawable );
pglXDestroyPixmap( gdi_display, gl->drawable );
XFreePixmap( gdi_display, gl->pixmap );
break;
......@@ -1251,13 +1255,15 @@ static void mark_drawable_dirty( struct gl_drawable *old, struct gl_drawable *ne
EnterCriticalSection( &context_section );
LIST_FOR_EACH_ENTRY( ctx, &context_list, struct wgl_context, entry )
{
if (old->drawable == ctx->drawables[0]) {
ctx->drawables[0] = new->drawable;
ctx->refresh_drawables = TRUE;
if (old == ctx->drawables[0] || old == ctx->new_drawables[0])
{
release_gl_drawable( ctx->new_drawables[0] );
ctx->new_drawables[0] = grab_gl_drawable( new );
}
if (old->drawable == ctx->drawables[1]) {
ctx->drawables[1] = new->drawable;
ctx->refresh_drawables = TRUE;
if (old == ctx->drawables[1] || old == ctx->new_drawables[1])
{
release_gl_drawable( ctx->new_drawables[1] );
ctx->new_drawables[1] = grab_gl_drawable( new );
}
}
LeaveCriticalSection( &context_section );
......@@ -1266,14 +1272,30 @@ static void mark_drawable_dirty( struct gl_drawable *old, struct gl_drawable *ne
/* Given the current context, make sure its drawable is sync'd */
static inline void sync_context(struct wgl_context *context)
{
BOOL refresh = FALSE;
EnterCriticalSection( &context_section );
if (context->refresh_drawables) {
if (context->new_drawables[0])
{
release_gl_drawable( context->drawables[0] );
context->drawables[0] = context->new_drawables[0];
context->new_drawables[0] = NULL;
refresh = TRUE;
}
if (context->new_drawables[1])
{
release_gl_drawable( context->drawables[1] );
context->drawables[1] = context->new_drawables[1];
context->new_drawables[1] = NULL;
refresh = TRUE;
}
if (refresh)
{
if (glxRequireVersion(3))
pglXMakeContextCurrent(gdi_display, context->drawables[0],
context->drawables[1], context->ctx);
pglXMakeContextCurrent(gdi_display, context->drawables[0]->drawable,
context->drawables[1]->drawable, context->ctx);
else
pglXMakeCurrent(gdi_display, context->drawables[0], context->ctx);
context->refresh_drawables = FALSE;
pglXMakeCurrent(gdi_display, context->drawables[0]->drawable, context->ctx);
}
LeaveCriticalSection( &context_section );
}
......@@ -1385,6 +1407,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel
if (gl->window)
gl->drawable = pglXCreateWindow( gdi_display, gl->format->fbconfig, gl->window, NULL );
release_win_data( data );
TRACE( "%p created client %lx drawable %lx\n", hwnd, gl->window, gl->drawable );
}
}
#ifdef SONAME_LIBXCOMPOSITE
......@@ -1425,6 +1448,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel
}
}
else XFreeColormap( gdi_display, gl->colormap );
TRACE( "%p created child %lx drawable %lx\n", hwnd, gl->window, gl->drawable );
}
#endif
else
......@@ -1837,6 +1861,10 @@ static BOOL glxdrv_wglDeleteContext(struct wgl_context *ctx)
LeaveCriticalSection( &context_section );
if (ctx->ctx) pglXDestroyContext( gdi_display, ctx->ctx );
release_gl_drawable( ctx->drawables[0] );
release_gl_drawable( ctx->drawables[1] );
release_gl_drawable( ctx->new_drawables[0] );
release_gl_drawable( ctx->new_drawables[1] );
return HeapFree( GetProcessHeap(), 0, ctx );
}
......@@ -1849,6 +1877,22 @@ static PROC glxdrv_wglGetProcAddress(LPCSTR lpszProc)
return pglXGetProcAddressARB((const GLubyte*)lpszProc);
}
static void set_context_drawables( struct wgl_context *ctx, struct gl_drawable *draw,
struct gl_drawable *read )
{
struct gl_drawable *prev[4];
int i;
prev[0] = ctx->drawables[0];
prev[1] = ctx->drawables[1];
prev[2] = ctx->new_drawables[0];
prev[3] = ctx->new_drawables[1];
ctx->drawables[0] = grab_gl_drawable( draw );
ctx->drawables[1] = read ? grab_gl_drawable( read ) : NULL;
ctx->new_drawables[0] = ctx->new_drawables[1] = NULL;
for (i = 0; i < 4; i++) release_gl_drawable( prev[i] );
}
/***********************************************************************
* glxdrv_wglMakeCurrent
*/
......@@ -1885,8 +1929,7 @@ static BOOL glxdrv_wglMakeCurrent(HDC hdc, struct wgl_context *ctx)
NtCurrentTeb()->glContext = ctx;
ctx->has_been_current = TRUE;
ctx->hdc = hdc;
ctx->drawables[0] = gl->drawable;
ctx->drawables[1] = gl->drawable;
set_context_drawables( ctx, gl, gl );
ctx->refresh_drawables = FALSE;
LeaveCriticalSection( &context_section );
goto done;
......@@ -1931,8 +1974,7 @@ static BOOL X11DRV_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, struct
{
ctx->has_been_current = TRUE;
ctx->hdc = draw_hdc;
ctx->drawables[0] = draw_gl->drawable;
ctx->drawables[1] = read_gl ? read_gl->drawable : 0;
set_context_drawables( ctx, draw_gl, read_gl );
ctx->refresh_drawables = FALSE;
NtCurrentTeb()->glContext = ctx;
LeaveCriticalSection( &context_section );
......
......@@ -1390,11 +1390,37 @@ static void move_window_bits( HWND hwnd, Window window, const RECT *old_rect, co
}
/***********************************************************************
* get_dummy_parent
*
* Create a dummy parent window for child windows that don't have a true X11 parent.
*/
static Window get_dummy_parent(void)
{
static Window dummy_parent;
if (!dummy_parent)
{
XSetWindowAttributes attrib;
attrib.override_redirect = True;
attrib.border_pixel = 0;
attrib.colormap = default_colormap;
dummy_parent = XCreateWindow( gdi_display, root_window, -1, -1, 1, 1, 0, default_visual.depth,
InputOutput, default_visual.visual,
CWColormap | CWBorderPixel | CWOverrideRedirect, &attrib );
XMapWindow( gdi_display, dummy_parent );
}
return dummy_parent;
}
/**********************************************************************
* create_client_window
*/
Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *visual )
{
Window dummy_parent = get_dummy_parent();
XSetWindowAttributes attr;
int x = data->client_rect.left - data->whole_rect.left;
int y = data->client_rect.top - data->whole_rect.top;
......@@ -1404,11 +1430,12 @@ Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *vi
if (data->client_window)
{
XDeleteContext( data->display, data->client_window, winContext );
XDestroyWindow( data->display, data->client_window );
XReparentWindow( gdi_display, data->client_window, dummy_parent, 0, 0 );
TRACE( "%p reparent xwin %lx/%lx\n", data->hwnd, data->whole_window, data->client_window );
}
if (data->colormap) XFreeColormap( data->display, data->colormap );
data->colormap = XCreateColormap( data->display, root_window, visual->visual,
if (data->colormap) XFreeColormap( gdi_display, data->colormap );
data->colormap = XCreateColormap( gdi_display, dummy_parent, visual->visual,
(visual->class == PseudoColor ||
visual->class == GrayScale ||
visual->class == DirectColor) ? AllocAll : AllocNone );
......@@ -1416,18 +1443,19 @@ Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *vi
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.backing_store = NotUseful;
attr.event_mask = ExposureMask;
attr.border_pixel = 0;
data->client_window = XCreateWindow( data->display, data->whole_window, x, y, cx, cy,
data->client_window = XCreateWindow( gdi_display, data->whole_window, x, y, cx, cy,
0, default_visual.depth, InputOutput, visual->visual,
CWBitGravity | CWWinGravity | CWBackingStore |
CWColormap | CWEventMask | CWBorderPixel, &attr );
CWColormap | CWBorderPixel, &attr );
if (!data->client_window) return 0;
TRACE( "%p xwin %lx/%lx\n", data->hwnd, data->whole_window, data->client_window );
XSaveContext( data->display, data->client_window, winContext, (char *)data->hwnd );
XMapWindow( data->display, data->client_window );
XSync( data->display, False );
XMapWindow( gdi_display, data->client_window );
XSync( gdi_display, False );
XSelectInput( data->display, data->client_window, ExposureMask );
return data->client_window;
}
......@@ -1528,9 +1556,17 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
}
TRACE( "win %p xwin %lx\n", data->hwnd, data->whole_window );
TRACE( "win %p xwin %lx/%lx\n", data->hwnd, data->whole_window, data->client_window );
XDeleteContext( data->display, data->whole_window, winContext );
if (data->client_window) XDeleteContext( data->display, data->client_window, winContext );
if (data->client_window)
{
XDeleteContext( data->display, data->client_window, winContext );
if (!already_destroyed)
{
XSelectInput( data->display, data->client_window, 0 );
XReparentWindow( data->display, data->client_window, get_dummy_parent(), 0, 0 );
}
}
if (!already_destroyed) XDestroyWindow( data->display, data->whole_window );
if (data->colormap) XFreeColormap( data->display, data->colormap );
data->whole_window = data->client_window = 0;
......@@ -1633,8 +1669,6 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd )
struct x11drv_thread_data *thread_data = x11drv_thread_data();
struct x11drv_win_data *data;
destroy_gl_drawable( hwnd );
if (!(data = get_win_data( hwnd ))) return;
destroy_whole_window( data, FALSE );
......@@ -1646,6 +1680,7 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd )
XDeleteContext( gdi_display, (XID)hwnd, win_data_context );
release_win_data( data );
HeapFree( GetProcessHeap(), 0, data );
destroy_gl_drawable( hwnd );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment