[cogl/wip/kms: 3/5] kms: Implement the swap buffers notify feature
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/kms: 3/5] kms: Implement the swap buffers notify feature
- Date: Thu, 5 Apr 2012 16:54:19 +0000 (UTC)
commit 311a0ae9863d9cddc04f81225a3c0d55e44ade0d
Author: Neil Roberts <neil linux intel com>
Date: Mon Dec 19 19:28:30 2011 +0000
kms: Implement the swap buffers notify feature
The KMS EGL platform now notifies when a swap is complete. The
notification is delayed until the application calls
cogl_context_dispatch. The GLX backend doesn't currently do this but I
think that is how it should behave to make it easier for the
application to handle locks and such.
cogl/winsys/cogl-winsys-egl-kms.c | 99 +++++++++++++++++++++++++++++++++----
1 files changed, 89 insertions(+), 10 deletions(-)
---
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 53b3890..2b9bdd6 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -68,6 +68,7 @@ typedef struct _CoglDisplayKMS
drmModeModeInfo mode;
drmModeCrtcPtr saved_crtc;
int width, height;
+ gboolean pending_swap_notify;
} CoglDisplayKMS;
typedef struct _CoglOnscreenKMS
@@ -77,6 +78,7 @@ typedef struct _CoglOnscreenKMS
uint32_t next_fb_id;
struct gbm_bo *current_bo;
struct gbm_bo *next_bo;
+ gboolean pending_swap_notify;
} CoglOnscreenKMS;
static const char device_name[] = "/dev/dri/card0";
@@ -313,13 +315,8 @@ _cogl_winsys_egl_cleanup_context (CoglDisplay *display)
}
static void
-page_flip_handler (int fd,
- unsigned int frame,
- unsigned int sec,
- unsigned int usec,
- void *data)
+free_current_bo (CoglOnscreen *onscreen)
{
- CoglOnscreen *onscreen = data;
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@@ -339,12 +336,36 @@ page_flip_handler (int fd,
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)
+{
+ CoglOnscreen *onscreen = data;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+
+ 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;
+
+ /* 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 */
+ kms_display->pending_swap_notify = TRUE;
+ kms_onscreen->pending_swap_notify = TRUE;
}
static void
@@ -409,6 +430,19 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
}
static gboolean
+_cogl_winsys_egl_context_init (CoglContext *context,
+ GError **error)
+{
+ COGL_FLAGS_SET (context->features,
+ COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, TRUE);
+ COGL_FLAGS_SET (context->winsys_features,
+ COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
+ TRUE);
+
+ return TRUE;
+}
+
+static gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
GError **error)
{
@@ -474,6 +508,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
CoglContext *context = framebuffer->context;
CoglRenderer *renderer = context->display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
CoglOnscreenKMS *kms_onscreen;
@@ -483,6 +518,12 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
kms_onscreen = egl_onscreen->platform;
+ /* If have a pending swap then block until it completes */
+ while (kms_onscreen->next_fb_id != 0)
+ handle_drm_event (kms_renderer);
+
+ free_current_bo (onscreen);
+
if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
@@ -506,13 +547,39 @@ _cogl_winsys_poll_get_info (CoglContext *context,
int *n_poll_fds,
gint64 *timeout)
{
- CoglRenderer *renderer = context->display->renderer;
+ CoglDisplay *display = context->display;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+ CoglRenderer *renderer = display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererKMS *kms_renderer = egl_renderer->platform;
*poll_fds = &kms_renderer->poll_fd;
*n_poll_fds = 1;
- *timeout = -1;
+
+ /* If we've already got a pending swap notify then we'll dispatch
+ immediately */
+ *timeout = kms_display->pending_swap_notify ? 0 : -1;
+}
+
+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)
+ {
+ _cogl_onscreen_notify_swap_buffers (onscreen);
+ kms_onscreen->pending_swap_notify = FALSE;
+ }
+ }
}
static void
@@ -520,7 +587,10 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
const CoglPollFD *poll_fds,
int n_poll_fds)
{
- CoglRenderer *renderer = context->display->renderer;
+ CoglDisplay *display = context->display;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+ CoglRenderer *renderer = display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererKMS *kms_renderer = egl_renderer->platform;
int i;
@@ -533,6 +603,14 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
break;
}
+
+ if (kms_display->pending_swap_notify)
+ {
+ g_list_foreach (context->framebuffers,
+ flush_pending_swap_notify_cb,
+ NULL);
+ kms_display->pending_swap_notify = FALSE;
+ }
}
static const CoglWinsysEGLVtable
@@ -541,7 +619,8 @@ _cogl_winsys_egl_vtable =
.display_setup = _cogl_winsys_egl_display_setup,
.display_destroy = _cogl_winsys_egl_display_destroy,
.context_created = _cogl_winsys_egl_context_created,
- .cleanup_context = _cogl_winsys_egl_cleanup_context
+ .cleanup_context = _cogl_winsys_egl_cleanup_context,
+ .context_init = _cogl_winsys_egl_context_init
};
const CoglWinsysVtable *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]