monado/src/xrt/state_trackers/oxr/oxr_event.c

223 lines
4.3 KiB
C
Raw Normal View History

2019-03-18 05:52:32 +00:00
// Copyright 2018-2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Holds event related functions.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup oxr_main
*/
#include "os/os_threading.h"
2019-03-18 05:52:32 +00:00
#include "util/u_misc.h"
2019-03-18 05:52:32 +00:00
#include "oxr_objects.h"
#include "oxr_logger.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
2019-03-18 05:52:32 +00:00
/*
*
* Struct and defines.
*
*/
2019-03-18 05:52:32 +00:00
struct oxr_event
{
struct oxr_event *next;
size_t length;
XrResult result;
2019-03-18 05:52:32 +00:00
};
/*
*
* Internal helpers.
*
*/
2019-03-18 05:52:32 +00:00
void
lock(struct oxr_instance *inst)
{
os_mutex_lock(&inst->event.mutex);
}
2019-03-18 05:52:32 +00:00
void
unlock(struct oxr_instance *inst)
{
os_mutex_unlock(&inst->event.mutex);
}
2019-03-18 05:52:32 +00:00
2019-10-08 14:28:15 +00:00
void *
oxr_event_extra(struct oxr_event *event)
{
return &event[1];
}
2019-03-18 05:52:32 +00:00
struct oxr_event *
pop(struct oxr_instance *inst)
{
struct oxr_event *ret = inst->event.next;
2019-03-18 05:52:32 +00:00
if (ret == NULL) {
return NULL;
}
inst->event.next = ret->next;
2019-03-18 05:52:32 +00:00
ret->next = NULL;
if (ret == inst->event.last) {
inst->event.last = NULL;
2019-03-18 05:52:32 +00:00
}
return ret;
}
void
push(struct oxr_instance *inst, struct oxr_event *event)
{
struct oxr_event *last = inst->event.last;
2019-03-18 05:52:32 +00:00
if (last != NULL) {
last->next = event;
}
inst->event.last = event;
2019-03-18 05:52:32 +00:00
if (inst->event.next == NULL) {
inst->event.next = event;
2019-03-18 05:52:32 +00:00
}
}
#define ALLOC(log, inst, event, extra) \
do { \
XrResult ret = \
oxr_event_alloc(log, inst, sizeof(**extra), event); \
if (ret != XR_SUCCESS) { \
return ret; \
} \
2019-10-08 14:28:15 +00:00
*((void **)extra) = oxr_event_extra(*event); \
2019-03-18 05:52:32 +00:00
} while (false)
static XrResult
oxr_event_alloc(struct oxr_logger *log,
struct oxr_instance *inst,
size_t size,
struct oxr_event **out_event)
{
struct oxr_event *event = U_CALLOC_WITH_CAST(
struct oxr_event, sizeof(struct oxr_event) + size);
2019-03-18 05:52:32 +00:00
if (event == NULL) {
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
"Out of memory");
2019-03-18 05:52:32 +00:00
}
event->next = NULL;
event->length = size;
event->result = XR_SUCCESS;
2019-03-18 05:52:32 +00:00
*out_event = event;
return XR_SUCCESS;
}
/*
*
* 'Exported' functions.
*
*/
2019-03-18 05:52:32 +00:00
XrResult
oxr_event_push_XrEventDataSessionStateChanged(struct oxr_logger *log,
struct oxr_session *sess,
XrSessionState state,
XrTime time)
{
struct oxr_instance *inst = sess->sys->inst;
XrEventDataSessionStateChanged *changed;
struct oxr_event *event = NULL;
2019-03-18 05:52:32 +00:00
ALLOC(log, inst, &event, &changed);
changed->type = XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED;
changed->session = oxr_session_to_openxr(sess);
changed->state = state;
changed->time = time;
event->result = state == XR_SESSION_STATE_LOSS_PENDING
? XR_SESSION_LOSS_PENDING
: XR_SUCCESS;
2019-03-18 05:52:32 +00:00
lock(inst);
push(inst, event);
unlock(inst);
return XR_SUCCESS;
}
XrResult
oxr_event_remove_session_events(struct oxr_logger *log,
struct oxr_session *sess)
{
struct oxr_instance *inst = sess->sys->inst;
XrSession session = oxr_session_to_openxr(sess);
lock(inst);
struct oxr_event *e = inst->event.next;
while (e != NULL) {
struct oxr_event *cur = e;
e = e->next;
XrEventDataSessionStateChanged *changed = oxr_event_extra(cur);
if (changed->type != XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
continue;
}
if (changed->session != session) {
continue;
}
if (cur == inst->event.next) {
inst->event.next = cur->next;
}
if (cur == inst->event.last) {
inst->event.last = NULL;
}
free(cur);
}
unlock(inst);
return XR_SUCCESS;
}
2019-03-18 05:52:32 +00:00
XrResult
oxr_poll_event(struct oxr_logger *log,
struct oxr_instance *inst,
XrEventDataBuffer *eventData)
{
struct oxr_session *sess = inst->sessions;
while (sess) {
oxr_session_poll(sess);
sess = sess->next;
}
2019-03-18 05:52:32 +00:00
lock(inst);
2019-10-08 14:28:15 +00:00
struct oxr_event *event = pop(inst);
2019-03-18 05:52:32 +00:00
unlock(inst);
if (event == NULL) {
return XR_EVENT_UNAVAILABLE;
}
XrResult ret = event->result;
2019-10-08 14:28:15 +00:00
memcpy(eventData, oxr_event_extra(event), event->length);
2019-03-18 05:52:32 +00:00
free(event);
return ret;
2019-03-18 05:52:32 +00:00
}