mirror of
https://github.com/brl/mutter.git
synced 2025-05-05 22:54:56 +00:00
Associate check and dispatch funcs with poll fds
Instead of driving event dispatching through a per winsys poll_dispatch vfunc its now possible to associate a check and dispatch function with each file descriptor that is registered for polling. This means we can remove the winsys get_dispatch_timeout and poll_dispatch vfuncs and it also makes it easier for more orthogonal internal components to add file descriptors for polling to the mainloop. Reviewed-by: Neil Roberts <neil@linux.intel.com> (cherry picked from commit 627947622df36dd529b9dc60a3ae9e6083532b19)
This commit is contained in:
parent
e3975d1711
commit
95a41e177a
@ -32,10 +32,16 @@
|
|||||||
void
|
void
|
||||||
_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd);
|
_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd);
|
||||||
|
|
||||||
|
typedef CoglBool (*CoglPollCheckCallback) (void *user_data);
|
||||||
|
typedef void (*CoglPollDispatchCallback) (void *user_data);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
|
_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
|
||||||
int fd,
|
int fd,
|
||||||
CoglPollFDEvent events);
|
CoglPollFDEvent events,
|
||||||
|
CoglPollCheckCallback check,
|
||||||
|
CoglPollDispatchCallback dispatch,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
typedef void (*CoglIdleCallback) (void *user_data);
|
typedef void (*CoglIdleCallback) (void *user_data);
|
||||||
|
|
||||||
|
@ -33,13 +33,21 @@
|
|||||||
#include "cogl-renderer-private.h"
|
#include "cogl-renderer-private.h"
|
||||||
#include "cogl-context-private.h"
|
#include "cogl-context-private.h"
|
||||||
|
|
||||||
|
typedef struct _CoglPollSource
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
CoglPollCheckCallback check;
|
||||||
|
CoglPollDispatchCallback dispatch;
|
||||||
|
void *user_data;
|
||||||
|
} CoglPollSource;
|
||||||
|
|
||||||
int
|
int
|
||||||
cogl_poll_renderer_get_info (CoglRenderer *renderer,
|
cogl_poll_renderer_get_info (CoglRenderer *renderer,
|
||||||
CoglPollFD **poll_fds,
|
CoglPollFD **poll_fds,
|
||||||
int *n_poll_fds,
|
int *n_poll_fds,
|
||||||
int64_t *timeout)
|
int64_t *timeout)
|
||||||
{
|
{
|
||||||
const CoglWinsysVtable *winsys;
|
GList *l;
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), 0);
|
_COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), 0);
|
||||||
_COGL_RETURN_VAL_IF_FAIL (poll_fds != NULL, 0);
|
_COGL_RETURN_VAL_IF_FAIL (poll_fds != NULL, 0);
|
||||||
@ -55,13 +63,17 @@ cogl_poll_renderer_get_info (CoglRenderer *renderer,
|
|||||||
return renderer->poll_fds_age;
|
return renderer->poll_fds_age;
|
||||||
}
|
}
|
||||||
|
|
||||||
winsys = renderer->winsys_vtable;
|
for (l = renderer->poll_sources; l; l = l->next)
|
||||||
|
{
|
||||||
if (winsys->get_dispatch_timeout)
|
CoglPollSource *source = l->data;
|
||||||
*timeout = winsys->get_dispatch_timeout (renderer);
|
if (source->check && source->check (source->user_data))
|
||||||
else
|
{
|
||||||
*timeout = -1;
|
*timeout = 0;
|
||||||
|
return renderer->poll_fds_age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*timeout = -1;
|
||||||
return renderer->poll_fds_age;
|
return renderer->poll_fds_age;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,16 +82,28 @@ cogl_poll_renderer_dispatch (CoglRenderer *renderer,
|
|||||||
const CoglPollFD *poll_fds,
|
const CoglPollFD *poll_fds,
|
||||||
int n_poll_fds)
|
int n_poll_fds)
|
||||||
{
|
{
|
||||||
const CoglWinsysVtable *winsys;
|
GList *l;
|
||||||
|
|
||||||
_COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
|
_COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
|
||||||
|
|
||||||
_cogl_closure_list_invoke_no_args (&renderer->idle_closures);
|
_cogl_closure_list_invoke_no_args (&renderer->idle_closures);
|
||||||
|
|
||||||
winsys = renderer->winsys_vtable;
|
for (l = renderer->poll_sources; l; l = l->next)
|
||||||
|
{
|
||||||
|
CoglPollSource *source = l->data;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (winsys->poll_dispatch)
|
for (i = 0; i < n_poll_fds; i++)
|
||||||
winsys->poll_dispatch (renderer, poll_fds, n_poll_fds);
|
{
|
||||||
|
const CoglPollFD *pollfd = &poll_fds[i];
|
||||||
|
|
||||||
|
if (pollfd->fd == source->fd)
|
||||||
|
{
|
||||||
|
source->dispatch (source->user_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -102,26 +126,51 @@ void
|
|||||||
_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd)
|
_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd)
|
||||||
{
|
{
|
||||||
int i = find_pollfd (renderer, fd);
|
int i = find_pollfd (renderer, fd);
|
||||||
|
GList *l;
|
||||||
|
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_array_remove_index_fast (renderer->poll_fds, i);
|
g_array_remove_index_fast (renderer->poll_fds, i);
|
||||||
renderer->poll_fds_age++;
|
renderer->poll_fds_age++;
|
||||||
|
|
||||||
|
for (l = renderer->poll_sources; l; l = l->next)
|
||||||
|
{
|
||||||
|
CoglPollSource *source = l->data;
|
||||||
|
if (source->fd == fd)
|
||||||
|
{
|
||||||
|
renderer->poll_sources =
|
||||||
|
g_list_delete_link (renderer->poll_sources, l);
|
||||||
|
g_slice_free (CoglPollSource, source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
|
_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
|
||||||
int fd,
|
int fd,
|
||||||
CoglPollFDEvent events)
|
CoglPollFDEvent events,
|
||||||
|
CoglPollCheckCallback check,
|
||||||
|
CoglPollDispatchCallback dispatch,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
CoglPollFD pollfd = {
|
CoglPollFD pollfd = {
|
||||||
fd,
|
fd,
|
||||||
events
|
events
|
||||||
};
|
};
|
||||||
|
CoglPollSource *source;
|
||||||
|
|
||||||
_cogl_poll_renderer_remove_fd (renderer, fd);
|
_cogl_poll_renderer_remove_fd (renderer, fd);
|
||||||
|
|
||||||
|
source = g_slice_new0 (CoglPollSource);
|
||||||
|
source->fd = fd;
|
||||||
|
source->check = check;
|
||||||
|
source->dispatch = dispatch;
|
||||||
|
source->user_data = user_data;
|
||||||
|
|
||||||
|
renderer->poll_sources = g_list_prepend (renderer->poll_sources, source);
|
||||||
|
|
||||||
g_array_append_val (renderer->poll_fds, pollfd);
|
g_array_append_val (renderer->poll_fds, pollfd);
|
||||||
renderer->poll_fds_age++;
|
renderer->poll_fds_age++;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ struct _CoglRenderer
|
|||||||
|
|
||||||
GArray *poll_fds;
|
GArray *poll_fds;
|
||||||
int poll_fds_age;
|
int poll_fds_age;
|
||||||
|
GList *poll_sources;
|
||||||
|
|
||||||
CoglClosureList idle_closures;
|
CoglClosureList idle_closures;
|
||||||
|
|
||||||
|
@ -84,11 +84,6 @@ _cogl_xlib_renderer_get_data (CoglRenderer *renderer);
|
|||||||
int64_t
|
int64_t
|
||||||
_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer);
|
_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer);
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds);
|
|
||||||
|
|
||||||
CoglOutput *
|
CoglOutput *
|
||||||
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
|
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
|
||||||
int x,
|
int x,
|
||||||
|
@ -468,6 +468,32 @@ randr_filter (XEvent *event,
|
|||||||
return COGL_FILTER_CONTINUE;
|
return COGL_FILTER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
check_xlib_events (void *user_data)
|
||||||
|
{
|
||||||
|
CoglRenderer *renderer = user_data;
|
||||||
|
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
|
||||||
|
|
||||||
|
return XPending (xlib_renderer->xdpy) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_xlib_events (void *user_data)
|
||||||
|
{
|
||||||
|
CoglRenderer *renderer = user_data;
|
||||||
|
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
|
||||||
|
|
||||||
|
if (renderer->xlib_enable_event_retrieval)
|
||||||
|
while (XPending (xlib_renderer->xdpy))
|
||||||
|
{
|
||||||
|
XEvent xevent;
|
||||||
|
|
||||||
|
XNextEvent (xlib_renderer->xdpy, &xevent);
|
||||||
|
|
||||||
|
cogl_xlib_renderer_handle_event (renderer, &xevent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CoglBool
|
CoglBool
|
||||||
_cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
|
_cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
|
||||||
{
|
{
|
||||||
@ -502,7 +528,10 @@ _cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
|
|||||||
{
|
{
|
||||||
_cogl_poll_renderer_add_fd (renderer,
|
_cogl_poll_renderer_add_fd (renderer,
|
||||||
ConnectionNumber (xlib_renderer->xdpy),
|
ConnectionNumber (xlib_renderer->xdpy),
|
||||||
COGL_POLL_FD_EVENT_IN);
|
COGL_POLL_FD_EVENT_IN,
|
||||||
|
check_xlib_events,
|
||||||
|
dispatch_xlib_events,
|
||||||
|
renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRSelectInput(xlib_renderer->xdpy,
|
XRRSelectInput(xlib_renderer->xdpy,
|
||||||
@ -589,24 +618,6 @@ _cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds)
|
|
||||||
{
|
|
||||||
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
|
|
||||||
|
|
||||||
if (renderer->xlib_enable_event_retrieval)
|
|
||||||
while (XPending (xlib_renderer->xdpy))
|
|
||||||
{
|
|
||||||
XEvent xevent;
|
|
||||||
|
|
||||||
XNextEvent (xlib_renderer->xdpy, &xevent);
|
|
||||||
|
|
||||||
cogl_xlib_renderer_handle_event (renderer, &xevent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CoglOutput *
|
CoglOutput *
|
||||||
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
|
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
|
||||||
int x,
|
int x,
|
||||||
|
@ -114,6 +114,143 @@ _cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
|
|||||||
g_slice_free (CoglRendererEGL, egl_renderer);
|
g_slice_free (CoglRendererEGL, egl_renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||||
|
|
||||||
|
if (kms_onscreen->pending_swap_notify)
|
||||||
|
{
|
||||||
|
CoglFrameInfo *info = g_queue_pop_head (&onscreen->pending_frame_infos);
|
||||||
|
|
||||||
|
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
||||||
|
_cogl_onscreen_notify_complete (onscreen, info);
|
||||||
|
kms_onscreen->pending_swap_notify = FALSE;
|
||||||
|
|
||||||
|
cogl_object_unref (info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flush_pending_swap_notify_idle (void *user_data)
|
||||||
|
{
|
||||||
|
CoglContext *context = user_data;
|
||||||
|
CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
|
||||||
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
|
|
||||||
|
/* This needs to be disconnected before invoking the callbacks in
|
||||||
|
* case the callbacks cause it to be queued again */
|
||||||
|
_cogl_closure_disconnect (kms_renderer->swap_notify_idle);
|
||||||
|
kms_renderer->swap_notify_idle = NULL;
|
||||||
|
|
||||||
|
g_list_foreach (context->framebuffers,
|
||||||
|
flush_pending_swap_notify_cb,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_current_bo (CoglOnscreen *onscreen)
|
||||||
|
{
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||||
|
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||||
|
CoglRenderer *renderer = context->display->renderer;
|
||||||
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
|
|
||||||
|
if (kms_onscreen->current_fb_id)
|
||||||
|
{
|
||||||
|
drmModeRmFB (kms_renderer->fd,
|
||||||
|
kms_onscreen->current_fb_id);
|
||||||
|
kms_onscreen->current_fb_id = 0;
|
||||||
|
}
|
||||||
|
if (kms_onscreen->current_bo)
|
||||||
|
{
|
||||||
|
gbm_surface_release_buffer (kms_onscreen->surface,
|
||||||
|
kms_onscreen->current_bo);
|
||||||
|
kms_onscreen->current_bo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_flip_handler (int fd,
|
||||||
|
unsigned int frame,
|
||||||
|
unsigned int sec,
|
||||||
|
unsigned int usec,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
CoglFlipKMS *flip = data;
|
||||||
|
|
||||||
|
/* We're only ready to dispatch a swap notification once all outputs
|
||||||
|
* have flipped... */
|
||||||
|
flip->pending--;
|
||||||
|
if (flip->pending == 0)
|
||||||
|
{
|
||||||
|
CoglOnscreen *onscreen = flip->onscreen;
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||||
|
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||||
|
CoglRenderer *renderer = context->display->renderer;
|
||||||
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
|
|
||||||
|
/* We only want to notify that the swap is complete when the
|
||||||
|
* application calls cogl_context_dispatch so instead of
|
||||||
|
* immediately notifying we queue an idle callback */
|
||||||
|
if (!kms_renderer->swap_notify_idle)
|
||||||
|
{
|
||||||
|
kms_renderer->swap_notify_idle =
|
||||||
|
_cogl_poll_renderer_add_idle (renderer,
|
||||||
|
flush_pending_swap_notify_idle,
|
||||||
|
context,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
kms_onscreen->pending_swap_notify = TRUE;
|
||||||
|
|
||||||
|
free_current_bo (onscreen);
|
||||||
|
|
||||||
|
kms_onscreen->current_fb_id = kms_onscreen->next_fb_id;
|
||||||
|
kms_onscreen->next_fb_id = 0;
|
||||||
|
|
||||||
|
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
||||||
|
kms_onscreen->next_bo = NULL;
|
||||||
|
|
||||||
|
cogl_object_unref (flip->onscreen);
|
||||||
|
|
||||||
|
g_slice_free (CoglFlipKMS, flip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_drm_event (CoglRendererKMS *kms_renderer)
|
||||||
|
{
|
||||||
|
drmEventContext evctx;
|
||||||
|
|
||||||
|
memset (&evctx, 0, sizeof evctx);
|
||||||
|
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
||||||
|
evctx.page_flip_handler = page_flip_handler;
|
||||||
|
drmHandleEvent (kms_renderer->fd, &evctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_kms_events (void *user_data)
|
||||||
|
{
|
||||||
|
CoglRenderer *renderer = user_data;
|
||||||
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
|
|
||||||
|
handle_drm_event (kms_renderer);
|
||||||
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
@ -161,7 +298,10 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
|||||||
|
|
||||||
_cogl_poll_renderer_add_fd (renderer,
|
_cogl_poll_renderer_add_fd (renderer,
|
||||||
kms_renderer->fd,
|
kms_renderer->fd,
|
||||||
COGL_POLL_FD_EVENT_IN);
|
COGL_POLL_FD_EVENT_IN,
|
||||||
|
NULL, /* no check callback */
|
||||||
|
dispatch_kms_events,
|
||||||
|
renderer);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -578,133 +718,6 @@ _cogl_winsys_egl_cleanup_context (CoglDisplay *display)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
free_current_bo (CoglOnscreen *onscreen)
|
|
||||||
{
|
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
||||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
|
||||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
|
||||||
CoglRenderer *renderer = context->display->renderer;
|
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
||||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
||||||
|
|
||||||
if (kms_onscreen->current_fb_id)
|
|
||||||
{
|
|
||||||
drmModeRmFB (kms_renderer->fd,
|
|
||||||
kms_onscreen->current_fb_id);
|
|
||||||
kms_onscreen->current_fb_id = 0;
|
|
||||||
}
|
|
||||||
if (kms_onscreen->current_bo)
|
|
||||||
{
|
|
||||||
gbm_surface_release_buffer (kms_onscreen->surface,
|
|
||||||
kms_onscreen->current_bo);
|
|
||||||
kms_onscreen->current_bo = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
||||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
|
||||||
|
|
||||||
if (kms_onscreen->pending_swap_notify)
|
|
||||||
{
|
|
||||||
CoglFrameInfo *info = g_queue_pop_head (&onscreen->pending_frame_infos);
|
|
||||||
|
|
||||||
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
|
||||||
_cogl_onscreen_notify_complete (onscreen, info);
|
|
||||||
kms_onscreen->pending_swap_notify = FALSE;
|
|
||||||
|
|
||||||
cogl_object_unref (info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
flush_pending_swap_notify_idle (void *user_data)
|
|
||||||
{
|
|
||||||
CoglContext *context = user_data;
|
|
||||||
CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
|
|
||||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
||||||
|
|
||||||
/* This needs to be disconnected before invoking the callbacks in
|
|
||||||
* case the callbacks cause it to be queued again */
|
|
||||||
_cogl_closure_disconnect (kms_renderer->swap_notify_idle);
|
|
||||||
kms_renderer->swap_notify_idle = NULL;
|
|
||||||
|
|
||||||
g_list_foreach (context->framebuffers,
|
|
||||||
flush_pending_swap_notify_cb,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
page_flip_handler (int fd,
|
|
||||||
unsigned int frame,
|
|
||||||
unsigned int sec,
|
|
||||||
unsigned int usec,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
CoglFlipKMS *flip = data;
|
|
||||||
|
|
||||||
/* We're only ready to dispatch a swap notification once all outputs
|
|
||||||
* have flipped... */
|
|
||||||
flip->pending--;
|
|
||||||
if (flip->pending == 0)
|
|
||||||
{
|
|
||||||
CoglOnscreen *onscreen = flip->onscreen;
|
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
||||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
|
||||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
|
||||||
CoglRenderer *renderer = context->display->renderer;
|
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
||||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
||||||
|
|
||||||
/* We only want to notify that the swap is complete when the
|
|
||||||
* application calls cogl_context_dispatch so instead of
|
|
||||||
* immediately notifying we queue an idle callback */
|
|
||||||
if (!kms_renderer->swap_notify_idle)
|
|
||||||
{
|
|
||||||
kms_renderer->swap_notify_idle =
|
|
||||||
_cogl_poll_renderer_add_idle (renderer,
|
|
||||||
flush_pending_swap_notify_idle,
|
|
||||||
context,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
kms_onscreen->pending_swap_notify = TRUE;
|
|
||||||
|
|
||||||
free_current_bo (onscreen);
|
|
||||||
|
|
||||||
kms_onscreen->current_fb_id = kms_onscreen->next_fb_id;
|
|
||||||
kms_onscreen->next_fb_id = 0;
|
|
||||||
|
|
||||||
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
|
||||||
kms_onscreen->next_bo = NULL;
|
|
||||||
|
|
||||||
cogl_object_unref (flip->onscreen);
|
|
||||||
|
|
||||||
g_slice_free (CoglFlipKMS, flip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_drm_event (CoglRendererKMS *kms_renderer)
|
|
||||||
{
|
|
||||||
drmEventContext evctx;
|
|
||||||
|
|
||||||
memset (&evctx, 0, sizeof evctx);
|
|
||||||
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
|
||||||
evctx.page_flip_handler = page_flip_handler;
|
|
||||||
drmHandleEvent (kms_renderer->fd, &evctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
|
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
|
||||||
{
|
{
|
||||||
@ -915,25 +928,6 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
|
|||||||
onscreen->winsys = NULL;
|
onscreen->winsys = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds)
|
|
||||||
{
|
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
||||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n_poll_fds; i++)
|
|
||||||
if (poll_fds[i].fd == kms_renderer->fd)
|
|
||||||
{
|
|
||||||
if (poll_fds[i].revents)
|
|
||||||
handle_drm_event (kms_renderer);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const CoglWinsysEGLVtable
|
static const CoglWinsysEGLVtable
|
||||||
_cogl_winsys_egl_vtable =
|
_cogl_winsys_egl_vtable =
|
||||||
{
|
{
|
||||||
@ -971,8 +965,6 @@ _cogl_winsys_egl_kms_get_vtable (void)
|
|||||||
vtable.onscreen_swap_region = NULL;
|
vtable.onscreen_swap_region = NULL;
|
||||||
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
|
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
|
||||||
|
|
||||||
vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
|
|
||||||
|
|
||||||
vtable_inited = TRUE;
|
vtable_inited = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "cogl-onscreen-private.h"
|
#include "cogl-onscreen-private.h"
|
||||||
#include "cogl-wayland-renderer.h"
|
#include "cogl-wayland-renderer.h"
|
||||||
#include "cogl-error-private.h"
|
#include "cogl-error-private.h"
|
||||||
|
#include "cogl-poll-private.h"
|
||||||
|
|
||||||
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ typedef struct _CoglRendererWayland
|
|||||||
struct wl_compositor *wayland_compositor;
|
struct wl_compositor *wayland_compositor;
|
||||||
struct wl_shell *wayland_shell;
|
struct wl_shell *wayland_shell;
|
||||||
struct wl_registry *wayland_registry;
|
struct wl_registry *wayland_registry;
|
||||||
CoglPollFD poll_fd;
|
int fd;
|
||||||
} CoglRendererWayland;
|
} CoglRendererWayland;
|
||||||
|
|
||||||
typedef struct _CoglDisplayWayland
|
typedef struct _CoglDisplayWayland
|
||||||
@ -108,6 +109,16 @@ static const struct wl_registry_listener registry_listener = {
|
|||||||
registry_handle_global_cb,
|
registry_handle_global_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_wayland_display_events (void *user_data)
|
||||||
|
{
|
||||||
|
CoglRenderer *renderer = user_data;
|
||||||
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
|
CoglRendererWayland *wayland_renderer = egl_renderer->platform;
|
||||||
|
|
||||||
|
wl_display_dispatch (wayland_renderer->wayland_display);
|
||||||
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
@ -176,9 +187,13 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
|||||||
if (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
|
if (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
wayland_renderer->poll_fd.fd =
|
wayland_renderer->fd = wl_display_get_fd(wayland_renderer->wayland_display);
|
||||||
wl_display_get_fd(wayland_renderer->wayland_display);
|
_cogl_poll_renderer_add_fd (renderer,
|
||||||
wayland_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
|
wayland_renderer->fd,
|
||||||
|
COGL_POLL_FD_EVENT_IN,
|
||||||
|
NULL, /* no check callback */
|
||||||
|
dispatch_wayland_display_events,
|
||||||
|
renderer);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -601,30 +616,6 @@ cogl_wayland_onscreen_resize (CoglOnscreen *onscreen,
|
|||||||
_cogl_framebuffer_winsys_update_size (fb, width, height);
|
_cogl_framebuffer_winsys_update_size (fb, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
|
||||||
_cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds)
|
|
||||||
{
|
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
||||||
CoglRendererWayland *wayland_renderer = egl_renderer->platform;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n_poll_fds; i++)
|
|
||||||
if (poll_fds[i].fd == wayland_renderer->poll_fd.fd)
|
|
||||||
{
|
|
||||||
if (poll_fds[i].revents & COGL_POLL_FD_EVENT_IN)
|
|
||||||
wl_display_dispatch (wayland_renderer->wayland_display);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const CoglWinsysEGLVtable
|
static const CoglWinsysEGLVtable
|
||||||
_cogl_winsys_egl_vtable =
|
_cogl_winsys_egl_vtable =
|
||||||
{
|
{
|
||||||
@ -659,9 +650,6 @@ _cogl_winsys_egl_wayland_get_vtable (void)
|
|||||||
|
|
||||||
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
|
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
|
||||||
|
|
||||||
vtable.get_dispatch_timeout = _cogl_winsys_get_dispatch_timeout;
|
|
||||||
vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
|
|
||||||
|
|
||||||
vtable_inited = TRUE;
|
vtable_inited = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,22 +668,6 @@ _cogl_winsys_xlib_get_visual_info (void)
|
|||||||
return get_visual_info (ctx->display, egl_display->egl_config);
|
return get_visual_info (ctx->display, egl_display->egl_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
|
||||||
_cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
|
|
||||||
{
|
|
||||||
return _cogl_xlib_renderer_get_dispatch_timeout (renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds)
|
|
||||||
{
|
|
||||||
_cogl_xlib_renderer_poll_dispatch (renderer,
|
|
||||||
poll_fds,
|
|
||||||
n_poll_fds);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EGL_KHR_image_pixmap
|
#ifdef EGL_KHR_image_pixmap
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
@ -830,9 +814,6 @@ _cogl_winsys_egl_xlib_get_vtable (void)
|
|||||||
|
|
||||||
vtable.xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info;
|
vtable.xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info;
|
||||||
|
|
||||||
vtable.get_dispatch_timeout = _cogl_winsys_get_dispatch_timeout;
|
|
||||||
vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
|
|
||||||
|
|
||||||
#ifdef EGL_KHR_image_pixmap
|
#ifdef EGL_KHR_image_pixmap
|
||||||
/* X11 tfp support... */
|
/* X11 tfp support... */
|
||||||
/* XXX: instead of having a rather monolithic winsys vtable we could
|
/* XXX: instead of having a rather monolithic winsys vtable we could
|
||||||
|
@ -2603,20 +2603,6 @@ _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
|
|||||||
return glx_tex_pixmap->glx_tex;
|
return glx_tex_pixmap->glx_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
|
||||||
_cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
|
|
||||||
{
|
|
||||||
return _cogl_xlib_renderer_get_dispatch_timeout (renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds)
|
|
||||||
{
|
|
||||||
_cogl_xlib_renderer_poll_dispatch (renderer, poll_fds, n_poll_fds);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglWinsysVtable _cogl_winsys_vtable =
|
static CoglWinsysVtable _cogl_winsys_vtable =
|
||||||
{
|
{
|
||||||
.id = COGL_WINSYS_ID_GLX,
|
.id = COGL_WINSYS_ID_GLX,
|
||||||
@ -2648,9 +2634,6 @@ static CoglWinsysVtable _cogl_winsys_vtable =
|
|||||||
.onscreen_set_resizable =
|
.onscreen_set_resizable =
|
||||||
_cogl_winsys_onscreen_set_resizable,
|
_cogl_winsys_onscreen_set_resizable,
|
||||||
|
|
||||||
.get_dispatch_timeout = _cogl_winsys_get_dispatch_timeout,
|
|
||||||
.poll_dispatch = _cogl_winsys_poll_dispatch,
|
|
||||||
|
|
||||||
/* X11 tfp support... */
|
/* X11 tfp support... */
|
||||||
/* XXX: instead of having a rather monolithic winsys vtable we could
|
/* XXX: instead of having a rather monolithic winsys vtable we could
|
||||||
* perhaps look for a way to separate these... */
|
* perhaps look for a way to separate these... */
|
||||||
|
@ -154,14 +154,6 @@ typedef struct _CoglWinsysVtable
|
|||||||
(*onscreen_win32_get_window) (CoglOnscreen *onscreen);
|
(*onscreen_win32_get_window) (CoglOnscreen *onscreen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int64_t
|
|
||||||
(*get_dispatch_timeout) (CoglRenderer *renderer);
|
|
||||||
|
|
||||||
void
|
|
||||||
(*poll_dispatch) (CoglRenderer *renderer,
|
|
||||||
const CoglPollFD *poll_fds,
|
|
||||||
int n_poll_fds);
|
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
CoglBool
|
CoglBool
|
||||||
(*texture_pixmap_x11_create) (CoglTexturePixmapX11 *tex_pixmap);
|
(*texture_pixmap_x11_create) (CoglTexturePixmapX11 *tex_pixmap);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user