glx: Only call swap_buffer callbacks @ dispatch time

This ensures we don't call swap buffer notify callback functions
immediately when they are received since it could be awkward for
applications to ensure they have dropped all necessary locks if they
don't know when callbacks might be invoked.

Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
Robert Bragg 2012-02-08 18:58:06 +00:00
parent 0f33c942f2
commit 15d43bb697
2 changed files with 50 additions and 1 deletions

View File

@ -50,6 +50,7 @@ typedef struct _CoglGLXDisplay
GLXContext glx_context; GLXContext glx_context;
GLXWindow dummy_glxwin; GLXWindow dummy_glxwin;
Window dummy_xwin; Window dummy_xwin;
gboolean pending_swap_notify;
} CoglGLXDisplay; } CoglGLXDisplay;
#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */ #endif /* __COGL_DISPLAY_GLX_PRIVATE_H */

View File

@ -81,6 +81,7 @@ typedef struct _CoglOnscreenGLX
GLXDrawable glxwin; GLXDrawable glxwin;
guint32 last_swap_vsync_counter; guint32 last_swap_vsync_counter;
GList *swap_callbacks; GList *swap_callbacks;
gboolean pending_swap_notify;
} CoglOnscreenGLX; } CoglOnscreenGLX;
typedef struct _CoglTexturePixmapGLX typedef struct _CoglTexturePixmapGLX
@ -163,11 +164,20 @@ static void
notify_swap_buffers (CoglContext *context, GLXDrawable drawable) notify_swap_buffers (CoglContext *context, GLXDrawable drawable)
{ {
CoglOnscreen *onscreen = find_onscreen_for_xid (context, (guint32)drawable); CoglOnscreen *onscreen = find_onscreen_for_xid (context, (guint32)drawable);
CoglDisplay *display = context->display;
CoglGLXDisplay *glx_display = display->winsys;
CoglOnscreenGLX *glx_onscreen;
if (!onscreen) if (!onscreen)
return; return;
_cogl_onscreen_notify_swap_buffers (onscreen); glx_onscreen = onscreen->winsys;
/* We only want to notify that the swap is complete when the
application calls cogl_context_dispatch so instead of immediately
notifying we'll set a flag to remember to notify later */
glx_display->pending_swap_notify = TRUE;
glx_onscreen->pending_swap_notify = TRUE;
} }
static CoglFilterReturn static CoglFilterReturn
@ -1959,10 +1969,37 @@ _cogl_winsys_poll_get_info (CoglContext *context,
int *n_poll_fds, int *n_poll_fds,
gint64 *timeout) gint64 *timeout)
{ {
CoglDisplay *display = context->display;
CoglGLXDisplay *glx_display = display->winsys;
_cogl_xlib_renderer_poll_get_info (context->display->renderer, _cogl_xlib_renderer_poll_get_info (context->display->renderer,
poll_fds, poll_fds,
n_poll_fds, n_poll_fds,
timeout); timeout);
/* If we've already got a pending swap notify then we'll dispatch
immediately */
if (glx_display->pending_swap_notify)
*timeout = 0;
}
static void
flush_pending_swap_notify_cb (void *data,
void *user_data)
{
CoglFramebuffer *framebuffer = data;
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
if (glx_onscreen->pending_swap_notify)
{
_cogl_onscreen_notify_swap_buffers (onscreen);
glx_onscreen->pending_swap_notify = FALSE;
}
}
} }
static void static void
@ -1970,9 +2007,20 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
CoglDisplay *display = context->display;
CoglGLXDisplay *glx_display = display->winsys;
_cogl_xlib_renderer_poll_dispatch (context->display->renderer, _cogl_xlib_renderer_poll_dispatch (context->display->renderer,
poll_fds, poll_fds,
n_poll_fds); n_poll_fds);
if (glx_display->pending_swap_notify)
{
g_list_foreach (context->framebuffers,
flush_pending_swap_notify_cb,
NULL);
glx_display->pending_swap_notify = FALSE;
}
} }
static CoglWinsysVtable _cogl_winsys_vtable = static CoglWinsysVtable _cogl_winsys_vtable =