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. Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
parent
cfefff1500
commit
f9d3ea03ec
@ -68,6 +68,7 @@ typedef struct _CoglDisplayKMS
|
|||||||
drmModeModeInfo mode;
|
drmModeModeInfo mode;
|
||||||
drmModeCrtcPtr saved_crtc;
|
drmModeCrtcPtr saved_crtc;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
gboolean pending_swap_notify;
|
||||||
} CoglDisplayKMS;
|
} CoglDisplayKMS;
|
||||||
|
|
||||||
typedef struct _CoglOnscreenKMS
|
typedef struct _CoglOnscreenKMS
|
||||||
@ -77,6 +78,7 @@ typedef struct _CoglOnscreenKMS
|
|||||||
uint32_t next_fb_id;
|
uint32_t next_fb_id;
|
||||||
struct gbm_bo *current_bo;
|
struct gbm_bo *current_bo;
|
||||||
struct gbm_bo *next_bo;
|
struct gbm_bo *next_bo;
|
||||||
|
gboolean pending_swap_notify;
|
||||||
} CoglOnscreenKMS;
|
} CoglOnscreenKMS;
|
||||||
|
|
||||||
static const char device_name[] = "/dev/dri/card0";
|
static const char device_name[] = "/dev/dri/card0";
|
||||||
@ -313,13 +315,8 @@ _cogl_winsys_egl_cleanup_context (CoglDisplay *display)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
page_flip_handler (int fd,
|
free_current_bo (CoglOnscreen *onscreen)
|
||||||
unsigned int frame,
|
|
||||||
unsigned int sec,
|
|
||||||
unsigned int usec,
|
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
CoglOnscreen *onscreen = data;
|
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||||
@ -339,12 +336,36 @@ page_flip_handler (int fd,
|
|||||||
kms_onscreen->current_bo);
|
kms_onscreen->current_bo);
|
||||||
kms_onscreen->current_bo = NULL;
|
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->current_fb_id = kms_onscreen->next_fb_id;
|
||||||
kms_onscreen->next_fb_id = 0;
|
kms_onscreen->next_fb_id = 0;
|
||||||
|
|
||||||
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
||||||
kms_onscreen->next_bo = NULL;
|
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
|
static void
|
||||||
@ -408,6 +429,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
|
static gboolean
|
||||||
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
|
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -474,6 +508,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
|
|||||||
CoglContext *context = framebuffer->context;
|
CoglContext *context = framebuffer->context;
|
||||||
CoglRenderer *renderer = context->display->renderer;
|
CoglRenderer *renderer = context->display->renderer;
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
CoglOnscreenKMS *kms_onscreen;
|
CoglOnscreenKMS *kms_onscreen;
|
||||||
|
|
||||||
@ -483,6 +518,12 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
|
|||||||
|
|
||||||
kms_onscreen = egl_onscreen->platform;
|
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)
|
if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
||||||
@ -506,13 +547,39 @@ _cogl_winsys_poll_get_info (CoglContext *context,
|
|||||||
int *n_poll_fds,
|
int *n_poll_fds,
|
||||||
gint64 *timeout)
|
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;
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
|
|
||||||
*poll_fds = &kms_renderer->poll_fd;
|
*poll_fds = &kms_renderer->poll_fd;
|
||||||
*n_poll_fds = 1;
|
*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
|
static void
|
||||||
@ -520,7 +587,10 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
|
|||||||
const CoglPollFD *poll_fds,
|
const CoglPollFD *poll_fds,
|
||||||
int n_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;
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||||
int i;
|
int i;
|
||||||
@ -533,6 +603,14 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
|
|||||||
|
|
||||||
break;
|
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
|
static const CoglWinsysEGLVtable
|
||||||
@ -541,7 +619,8 @@ _cogl_winsys_egl_vtable =
|
|||||||
.display_setup = _cogl_winsys_egl_display_setup,
|
.display_setup = _cogl_winsys_egl_display_setup,
|
||||||
.display_destroy = _cogl_winsys_egl_display_destroy,
|
.display_destroy = _cogl_winsys_egl_display_destroy,
|
||||||
.context_created = _cogl_winsys_egl_context_created,
|
.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 *
|
const CoglWinsysVtable *
|
||||||
|
Loading…
Reference in New Issue
Block a user