Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 116 additions & 33 deletions extension/T5Integration/Glasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,24 @@ bool Glasses::allocate_handle(T5_Context context) {
LOG_T5_ERROR(result);
return false;
}
_state.set(GlassesState::CREATED);
_state.clear(GlassesState::UNAVAILABLE);
_scheduler->add_task(monitor_parameters());

return true;
}

void Glasses::set_existing(bool exists) {
if (exists == is_existing())
return;
if (exists) {
if (_state.set_and_was_toggled(GlassesState::EXISTS))
_scheduler->add_task(monitor_parameters());
_state.clear(GlassesState::UNAVAILABLE);
} else {
_state.clear(GlassesState::EXISTS);
_state.set(GlassesState::UNAVAILABLE);
disconnect();
}
}

void Glasses::destroy_handle() {
_state.clear_all();
{
Expand All @@ -174,6 +185,11 @@ void Glasses::destroy_handle() {
}

CotaskPtr Glasses::monitor_connection() {
//Shouldn't be possible to have multiple of these running at once
MonitorFlags::ScopeGuard guard(_async_functions_running, CONNECTION_MONITOR_FUNC_RUNNING);
if (!guard.was_toggled())
co_return;

T5_Result result;

while (_glasses_handle && _state.is_current(GlassesState::SUSTAIN_CONNECTION)) {
Expand Down Expand Up @@ -201,28 +217,23 @@ CotaskPtr Glasses::monitor_connection() {
std::lock_guard lock(g_t5_exclusivity_group_1);
result = t5ReserveGlasses(_glasses_handle, _application_name.c_str());
}
if (result == T5_SUCCESS || result == T5_ERROR_ALREADY_CONNECTED)
if (result == T5_SUCCESS || result == T5_ERROR_ALREADY_CONNECTED) {
_state.clear(GlassesState::UNAVAILABLE);
continue;
else if (result == T5_ERROR_UNAVAILABLE) {
} else if (result == T5_ERROR_UNAVAILABLE) {
// Some else has the glasses so stop
// trying to connect
_state.clear(GlassesState::SUSTAIN_CONNECTION);
_state.set(GlassesState::UNAVAILABLE);
co_return;
} else if (result == T5_ERROR_DEVICE_LOST) {
_state.clear(GlassesState::SUSTAIN_CONNECTION);
co_await run_in_foreground;
LOG_T5_ERROR(result);
destroy_handle();
co_return;
}
_state.reset(GlassesState::ERROR);
co_await run_in_foreground;
LOG_T5_ERROR(result);
co_return;
}
case kT5_ConnectionState_ExclusiveReservation:
case kT5_ConnectionState_Disconnected: {
case kT5_ConnectionState_Disconnected:
case kT5_ConnectionState_ExclusiveReservation: {
_state.clear(GlassesState::READY);

{
Expand All @@ -239,11 +250,6 @@ CotaskPtr Glasses::monitor_connection() {
// trying to connect
_state.clear(GlassesState::SUSTAIN_CONNECTION);
_state.set(GlassesState::UNAVAILABLE);
} else if (result == T5_ERROR_DEVICE_LOST) {
_state.clear(GlassesState::SUSTAIN_CONNECTION);
co_await run_in_foreground;
LOG_T5_ERROR(result);
destroy_handle();
} else {
_state.reset(GlassesState::ERROR);
co_await run_in_foreground;
Expand Down Expand Up @@ -278,14 +284,79 @@ CotaskPtr Glasses::monitor_connection() {
}
}

CotaskPtr Glasses::monitor_unavailable() {
//Shouldn't be possible to have multiple of these running at once
MonitorFlags::ScopeGuard guard(_async_functions_running, UNAVAILABLE_MONITOR_FUNC_RUNNING);
if (!guard.was_toggled())
co_return;

T5_Result result;

while (_glasses_handle && _state.is_current(GlassesState::EXISTS | GlassesState::UNAVAILABLE)) {
T5_ConnectionState connectionState;

{
std::lock_guard lock(g_t5_exclusivity_group_1);
result = t5GetGlassesConnectionState(_glasses_handle, &connectionState);
}
if (result != T5_SUCCESS) {
// Doesn't seem to be anything recoverable here
co_await run_in_foreground;
LOG_T5_ERROR(result);
_state.reset(GlassesState::ERROR);
co_return;
}

switch (connectionState) {
case kT5_ConnectionState_NotExclusivelyConnected: {
_state.clear(GlassesState::READY);
{
std::lock_guard lock(g_t5_exclusivity_group_1);
result = t5ReserveGlasses(_glasses_handle, _application_name.c_str());
}
if (result == T5_SUCCESS) {
_state.clear(GlassesState::UNAVAILABLE);
{
std::lock_guard lock(g_t5_exclusivity_group_1);
result = t5ReleaseGlasses(_glasses_handle);
}
co_return;
} else if (result == T5_ERROR_ALREADY_CONNECTED) {
_state.clear(GlassesState::UNAVAILABLE);
co_return;
} else if (result != T5_ERROR_UNAVAILABLE) {
_state.reset(GlassesState::ERROR);
co_await run_in_foreground;
LOG_T5_ERROR(result);
co_return;
}
break;
}
case kT5_ConnectionState_Disconnected:
case kT5_ConnectionState_ExclusiveReservation:
case kT5_ConnectionState_ExclusiveConnection: {
_state.clear(GlassesState::UNAVAILABLE);
co_return;
}
}

co_await task_sleep(_poll_rate_for_monitoring);
}
}

CotaskPtr Glasses::monitor_parameters() {
//Shouldn't be possible to have multiple of these running at once
MonitorFlags::ScopeGuard guard(_async_functions_running, PARAMETER_MONITOR_FUNC_RUNNING);
if (!guard.was_toggled())
co_return;

co_await query_ipd();
co_await query_friendly_name();

T5_Result result;
std::vector<T5_ParamGlasses> _changed_params;

while (_glasses_handle && _state.is_current(GlassesState::CREATED)) {
while (_glasses_handle && _state.is_current(GlassesState::EXISTS)) {
co_await task_sleep(_poll_rate_for_monitoring);

uint16_t buffer_size = 16;
Expand Down Expand Up @@ -320,6 +391,11 @@ CotaskPtr Glasses::monitor_parameters() {
}

CotaskPtr Glasses::monitor_wands() {
//Shouldn't be possible to have multiple of these running at once
MonitorFlags::ScopeGuard guard(_async_functions_running, WAND_MONITOR_FUNC_RUNNING);
if (!guard.was_toggled())
co_return;

WandService wand_service;

if (!wand_service.start(_glasses_handle))
Expand All @@ -333,7 +409,7 @@ CotaskPtr Glasses::monitor_wands() {
co_return;
}

while (_glasses_handle && _state.is_current(GlassesState::SUSTAIN_CONNECTION) && wand_service.is_running()) {
while (_glasses_handle && _state.is_current(GlassesState::READY | GlassesState::SUSTAIN_CONNECTION) && wand_service.is_running()) {
auto err = wand_service.get_last_error();
if (err != T5_SUCCESS) {
LOG_T5_ERROR(err);
Expand Down Expand Up @@ -414,6 +490,11 @@ void Glasses::connect(const std::string_view application_name) {
}

void Glasses::disconnect() {
release_glasses();
_state.clear(GlassesState::SUSTAIN_CONNECTION);
}

void Glasses::release_glasses() {
if (_state.is_current(GlassesState::READY)) {
T5_Result result;
{
Expand All @@ -424,19 +505,19 @@ void Glasses::disconnect() {
LOG_T5_ERROR(result);
}
}
_state.clear(GlassesState::READY | GlassesState::GRAPHICS_INIT | GlassesState::SUSTAIN_CONNECTION);
_state.clear(GlassesState::CONNECTED | GlassesState::READY | GlassesState::GRAPHICS_INIT);
on_glasses_released();
}

void Glasses::start_display() {
if (_state.set_and_was_toggled(GlassesState::DISPLAY_STARTED)) {
on_start_display();
void Glasses::alloc_render_textures() {
if (_state.set_and_was_toggled(GlassesState::TEXTURES_ALLOCATED)) {
on_allocate_render_textures();
}
}

void Glasses::stop_display() {
if (_state.clear_and_was_toggled(GlassesState::DISPLAY_STARTED)) {
on_stop_display();
void Glasses::dealloc_render_textures() {
if (_state.clear_and_was_toggled(GlassesState::TEXTURES_ALLOCATED)) {
on_deallocate_render_textures();
}
}

Expand Down Expand Up @@ -477,7 +558,7 @@ void Glasses::update_pose() {
if (result == T5_ERROR_TRY_AGAIN)
return;
else if (result == T5_ERROR_NOT_CONNECTED) {
_state.clear(GlassesState::CONNECTED);
_state.clear(GlassesState::CONNECTED | GlassesState::READY);
LOG_T5_ERROR(result);
} else {
LOG_T5_ERROR(result);
Expand Down Expand Up @@ -512,7 +593,7 @@ void Glasses::get_eye_position(Eye eye, T5_Vec3& pos) {
}

void Glasses::send_frame() {
if (_state.is_current(GlassesState::TRACKING | GlassesState::CONNECTED)) {
if (_state.is_current(GlassesState::TRACKING | GlassesState::CONNECTED | GlassesState::TEXTURES_ALLOCATED)) {
on_send_frame(_current_frame_idx);

T5_FrameInfo frameInfo;
Expand Down Expand Up @@ -552,7 +633,7 @@ void Glasses::send_frame() {
return;
LOG_T5_ERROR(result);
if (result == T5_ERROR_NOT_CONNECTED) {
_state.clear(GlassesState::CONNECTED);
_state.clear(GlassesState::CONNECTED | GlassesState::READY);
}
// not sure how we might get here
else if (result == T5_ERROR_GFX_CONTEXT_INIT_FAIL || result == T5_ERROR_INVALID_GFX_CONTEXT) {
Expand All @@ -568,9 +649,11 @@ bool Glasses::update_connection() {
on_glasses_reserved();
}
if (_state.became_clear(_previous_update_state, GlassesState::CONNECTED)) {
stop_display();
on_glasses_dropped();
}
if (_state.became_set(_previous_update_state, GlassesState::UNAVAILABLE)) {
_scheduler->add_task(monitor_unavailable());
}
_previous_update_state.sync_from(_state);

return true;
Expand All @@ -583,10 +666,10 @@ bool Glasses::update_tracking() {
}

void Glasses::get_events(int index, std::vector<GlassesEvent>& out_events) {
if (_state.became_set(_previous_event_state, GlassesState::CREATED)) {
if (_state.became_set(_previous_event_state, GlassesState::EXISTS)) {
out_events.push_back(GlassesEvent(index, GlassesEvent::E_ADDED));
}
if (_state.became_clear(_previous_event_state, GlassesState::CREATED)) {
if (_state.became_clear(_previous_event_state, GlassesState::EXISTS)) {
out_events.push_back(GlassesEvent(index, GlassesEvent::E_LOST));
}

Expand Down
36 changes: 25 additions & 11 deletions extension/T5Integration/Glasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace T5Integration {

using namespace std::chrono_literals;
using GlassesFlags = StateFlags<uint16_t>;
using MonitorFlags = StateFlags<uint8_t>;
class T5Service;
using TaskSystem::CotaskPtr;
using TaskSystem::Scheduler;
Expand All @@ -22,13 +23,13 @@ namespace GlassesState {
const uint16_t GRAPHICS_INIT = 0x00000002; //0000000010
const uint16_t SUSTAIN_CONNECTION = 0x00000004; //0000000100

const uint16_t CREATED = 0x00000008; //0000001000
const uint16_t EXISTS = 0x00000008; //0000001000
const uint16_t UNAVAILABLE = 0x00000010; //0000010000
const uint16_t TRACKING = 0x00000020; //0000100000
const uint16_t CONNECTED = 0x00000040; //0001000000
const uint16_t TRACKING_WANDS = 0x00000080; //0010000000
const uint16_t ERROR = 0x00000100; //0100000000
const uint16_t DISPLAY_STARTED = 0x00000200; //1000000000
const uint16_t TEXTURES_ALLOCATED = 0x00000200; //1000000000
}
// clang-format on

Expand Down Expand Up @@ -81,16 +82,18 @@ class Glasses {

const std::string get_id();
const std::string get_name();
bool is_existing();
bool is_connected();
bool is_available();
bool is_tracking();

bool allocate_handle(T5_Context context);
void set_existing(bool exists);
void destroy_handle();
void connect(const std::string_view application_name);
void disconnect();
void start_display();
void stop_display();
void alloc_render_textures();
void dealloc_render_textures();

float get_ipd();
float get_fov();
Expand Down Expand Up @@ -132,8 +135,10 @@ class Glasses {
void set_swap_chain_texture_pair(int swap_chain_idx, intptr_t left_eye_handle, intptr_t right_eye_handle);
void set_swap_chain_texture_array(int swap_chain_idx, intptr_t array_handle);

virtual void on_start_display() {}
virtual void on_stop_display() {}
void release_glasses();

virtual void on_allocate_render_textures() {}
virtual void on_deallocate_render_textures() {}
virtual void on_glasses_reserved() {}
virtual void on_glasses_released() {}
virtual void on_glasses_dropped() {}
Expand All @@ -148,9 +153,8 @@ class Glasses {
CotaskPtr monitor_wands();
CotaskPtr query_ipd();
CotaskPtr query_friendly_name();
CotaskPtr monitor_unavailable();

bool reserve();
bool make_ready();
bool initialize_graphics();

void configure_wand_tracking();
Expand All @@ -159,9 +163,6 @@ class Glasses {

void get_eye_position(Eye eye, T5_Vec3& pos);

void begin_reserved_state();
void end_reserved_state();

private:
Scheduler::Ptr _scheduler;
T5Math::Ptr _math;
Expand All @@ -188,6 +189,15 @@ class Glasses {
std::chrono::milliseconds _poll_rate_for_connecting = 100ms;
std::chrono::milliseconds _poll_rate_for_monitoring = 2s;
std::chrono::milliseconds _wait_time_for_wand_IO = 100s;

std::chrono::steady_clock::time_point _last_time_available_checked;

const uint8_t CONNECTION_MONITOR_FUNC_RUNNING = 0x01;
const uint8_t PARAMETER_MONITOR_FUNC_RUNNING = 0x02;
const uint8_t WAND_MONITOR_FUNC_RUNNING = 0x04;
const uint8_t UNAVAILABLE_MONITOR_FUNC_RUNNING = 0x08;

MonitorFlags _async_functions_running;
};

inline const std::string Glasses::get_id() {
Expand All @@ -198,6 +208,10 @@ inline const std::string Glasses::get_name() {
return _friendly_name;
}

inline bool Glasses::is_existing() {
return _state.is_current(GlassesState::EXISTS);
}

inline bool Glasses::is_connected() {
return _state.is_current(GlassesState::CONNECTED);
}
Expand Down
Loading