Ver código fonte

Refactor OsEventQueue

Daniele Bartolini 9 anos atrás
pai
commit
2a65e7b8de

+ 52 - 65
src/device/device.cpp

@@ -11,6 +11,7 @@
 #include "console_server.h"
 #include "data_compiler.h"
 #include "device.h"
+#include "device_event_queue.h"
 #include "file.h"
 #include "filesystem.h"
 #include "filesystem_apk.h"
@@ -30,7 +31,6 @@
 #include "memory.h"
 #include "mesh_resource.h"
 #include "os.h"
-#include "os_event_queue.h"
 #include "package_resource.h"
 #include "path.h"
 #include "physics.h"
@@ -172,124 +172,111 @@ Device::Device(const DeviceOptions& opts)
 
 bool Device::process_events(s16& mouse_x, s16& mouse_y, s16& mouse_last_x, s16& mouse_last_y, bool vsync)
 {
-	OsEvent event;
-	bool exit = false;
 	InputManager* im = _input_manager;
+	bool exit = false;
+	bool reset = false;
 
-	const s16 dt_x = mouse_x - mouse_last_x;
-	const s16 dt_y = mouse_y - mouse_last_y;
-	im->mouse()->set_axis(MouseAxis::CURSOR_DELTA, vector3(dt_x, dt_y, 0.0f));
-	mouse_last_x = mouse_x;
-	mouse_last_y = mouse_y;
-
+	OsEvent event;
 	while(next_event(event))
 	{
-		if (event.type == OsEvent::NONE)
+		if (event.type == OsEventType::NONE)
 			continue;
 
 		switch (event.type)
 		{
-		case OsEvent::TOUCH:
+		case OsEventType::BUTTON:
 			{
-				const OsTouchEvent& ev = event.touch;
-				switch (ev.type)
+				const ButtonEvent ev = event.button;
+				switch (ev.device_id)
 				{
-				case OsTouchEvent::POINTER:
-					im->touch()->set_button_state(ev.pointer_id, ev.pressed);
+				case InputDeviceType::KEYBOARD:
+					im->keyboard()->set_button_state(ev.button_num, ev.pressed);
+					break;
+
+				case InputDeviceType::MOUSE:
+					im->mouse()->set_button_state(ev.button_num, ev.pressed);
 					break;
 
-				case OsTouchEvent::MOVE:
-					im->touch()->set_axis(ev.pointer_id, vector3(ev.x, ev.y, 0.0f));
+				case InputDeviceType::TOUCHSCREEN:
+					im->touch()->set_button_state(ev.button_num, ev.pressed);
 					break;
 
-				default:
-					CE_FATAL("Unknown touch event type");
+				case InputDeviceType::JOYPAD:
+					im->joypad(ev.device_num)->set_button_state(ev.button_num, ev.pressed);
 					break;
 				}
 			}
 			break;
 
-		case OsEvent::MOUSE:
+		case OsEventType::AXIS:
 			{
-				const OsMouseEvent& ev = event.mouse;
-				switch (ev.type)
+				const AxisEvent ev = event.axis;
+				switch (ev.device_id)
 				{
-				case OsMouseEvent::BUTTON:
-					im->mouse()->set_button_state(ev.button, ev.pressed);
-					break;
-
-				case OsMouseEvent::MOVE:
-					mouse_x = ev.x;
-					mouse_y = ev.y;
-					im->mouse()->set_axis(MouseAxis::CURSOR, vector3(ev.x, ev.y, 0.0f));
-					break;
-
-				case OsMouseEvent::WHEEL:
-					im->mouse()->set_axis(MouseAxis::WHEEL, vector3(0.0f, ev.wheel, 0.0f));
+				case InputDeviceType::MOUSE:
+					im->mouse()->set_axis(ev.axis_num, vector3(ev.axis_x, ev.axis_y, ev.axis_z));
+					if (ev.axis_num == MouseAxis::CURSOR)
+					{
+						mouse_x = ev.axis_x;
+						mouse_y = ev.axis_y;
+					}
 					break;
 
-				default:
-					CE_FATAL("Unknown mouse event type");
+				case InputDeviceType::JOYPAD:
+					im->joypad(ev.device_num)->set_axis(ev.axis_num, vector3(ev.axis_x, ev.axis_y, ev.axis_z));
 					break;
 				}
 			}
 			break;
 
-		case OsEvent::KEYBOARD:
-			im->keyboard()->set_button_state(event.keyboard.button, event.keyboard.pressed);
-			break;
-
-		case OsEvent::JOYPAD:
+		case OsEventType::STATUS:
 			{
-				const OsJoypadEvent& ev = event.joypad;
-				switch (ev.type)
+				const StatusEvent ev = event.status;
+				switch (ev.device_id)
 				{
-				case OsJoypadEvent::CONNECTED:
-					im->joypad(ev.index)->set_connected(ev.connected);
-					break;
-
-				case OsJoypadEvent::BUTTON:
-					im->joypad(ev.index)->set_button_state(ev.button, ev.pressed);
-					break;
-
-				case OsJoypadEvent::AXIS:
-					im->joypad(ev.index)->set_axis(ev.button, vector3(ev.x, ev.y, ev.z));
-					break;
-
-				default:
-					CE_FATAL("Unknown joypad event");
+				case InputDeviceType::JOYPAD:
+					im->joypad(ev.device_num)->set_connected(ev.connected);
 					break;
 				}
 			}
 			break;
 
-		case OsEvent::METRICS:
+		case OsEventType::RESOLUTION:
 			{
-				const OsMetricsEvent& ev = event.metrics;
-				_width = ev.width;
+				const ResolutionEvent& ev = event.resolution;
+				_width  = ev.width;
 				_height = ev.height;
-				bgfx::reset(ev.width, ev.height, (vsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE));
+				reset   = true;
 			}
 			break;
 
-		case OsEvent::EXIT:
+		case OsEventType::EXIT:
 			exit = true;
 			break;
 
-		case OsEvent::PAUSE:
+		case OsEventType::PAUSE:
 			pause();
 			break;
 
-		case OsEvent::RESUME:
+		case OsEventType::RESUME:
 			unpause();
 			break;
 
 		default:
-			CE_FATAL("Unknown os event");
+			CE_FATAL("Unknown OS event");
 			break;
 		}
 	}
 
+	const s16 dt_x = mouse_x - mouse_last_x;
+	const s16 dt_y = mouse_y - mouse_last_y;
+	im->mouse()->set_axis(MouseAxis::CURSOR_DELTA, vector3(dt_x, dt_y, 0.0f));
+	mouse_last_x = mouse_x;
+	mouse_last_y = mouse_y;
+
+	if (reset)
+		bgfx::reset(_width, _height, (vsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE));
+
 	return exit;
 }
 

+ 185 - 0
src/device/device_event_queue.h

@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#pragma once
+
+#include "types.h"
+#include "input_types.h"
+#include "math_types.h"
+#include "atomic_int.h"
+
+namespace crown
+{
+struct OsEventType
+{
+	enum Enum
+	{
+		BUTTON,
+		AXIS,
+		STATUS,
+		RESOLUTION,
+		EXIT,
+		PAUSE,
+		RESUME,
+		NONE
+	};
+};
+
+struct ButtonEvent
+{
+	u16 type;
+	u16 device_id  : 3;
+	u16 device_num : 2;
+	u16 button_num : 8;
+	u16 pressed    : 1;
+};
+
+struct AxisEvent
+{
+	u16 type;
+	u16 device_id  : 3;
+	u16 device_num : 2;
+	u16 axis_num   : 4;
+	f32 axis_x;
+	f32 axis_y;
+	f32 axis_z;
+};
+
+struct StatusEvent
+{
+	u16 type;
+	u16 device_id  : 3;
+	u16 device_num : 2;
+	u16 connected  : 1;
+};
+
+struct ResolutionEvent
+{
+	u16 type;
+	u16 width;
+	u16 height;
+};
+
+union OsEvent
+{
+	u16 type;
+	ButtonEvent button;
+	AxisEvent axis;
+	StatusEvent status;
+	ResolutionEvent resolution;
+};
+
+#define MAX_OS_EVENTS 4096
+
+/// Single Producer Single Consumer event queue.
+/// Used only to pass events from os thread to main thread.
+struct DeviceEventQueue
+{
+	DeviceEventQueue()
+		: _tail(0)
+		, _head(0)
+	{
+	}
+
+	void push_button_event(u16 device_id, u16 device_num, u16 button_id, bool pressed)
+	{
+		OsEvent ev;
+		ev.button.type = OsEventType::BUTTON;
+		ev.button.device_id = device_id;
+		ev.button.device_num = device_num;
+		ev.button.button_num = button_id;
+		ev.button.pressed = pressed;
+
+		push_event(ev);
+	}
+
+	void push_axis_event(u16 device_id, u16 device_num, u16 axis_id, f32 axis_x, f32 axis_y, f32 axis_z)
+	{
+		OsEvent ev;
+		ev.axis.type = OsEventType::AXIS;
+		ev.axis.device_id = device_id;
+		ev.axis.device_num = device_num;
+		ev.axis.axis_num = axis_id;
+		ev.axis.axis_x = axis_x;
+		ev.axis.axis_y = axis_y;
+		ev.axis.axis_z = axis_z;
+
+		push_event(ev);
+	}
+
+	void push_status_event(u16 device_id, u16 device_num, bool connected)
+	{
+		OsEvent ev;
+		ev.status.type = OsEventType::STATUS;
+		ev.status.device_id = device_id;
+		ev.status.device_num = device_num;
+		ev.status.connected = connected;
+
+		push_event(ev);
+	}
+
+	void push_resolution_event(u16 width, u16 height)
+	{
+		OsEvent ev;
+		ev.resolution.type = OsEventType::RESOLUTION;
+		ev.resolution.width = width;
+		ev.resolution.height = height;
+
+		push_event(ev);
+	}
+
+	void push_exit_event()
+	{
+		OsEvent ev;
+		ev.type = OsEventType::EXIT;
+
+		push_event(ev);
+	}
+
+	void push_none_event()
+	{
+		OsEvent ev;
+		ev.type = OsEventType::NONE;
+
+		push_event(ev);
+	}
+
+	bool push_event(const OsEvent& ev)
+	{
+		int cur_tail = _tail.load();
+		int next_tail = increment(cur_tail);
+		if(next_tail != _head.load())
+		{
+			_queue[cur_tail] = ev;
+			_tail.store(next_tail);
+			return true;
+		}
+
+		return false;
+	}
+
+	bool pop_event(OsEvent& ev)
+	{
+		const int cur_head = _head.load();
+		if(cur_head == _tail.load()) return false;
+
+		ev = _queue[cur_head];
+		_head.store(increment(cur_head));
+		return true;
+	}
+
+	int increment(int idx) const
+	{
+	  return (idx + 1) % MAX_OS_EVENTS;
+	}
+
+private:
+
+	OsEvent _queue[MAX_OS_EVENTS];
+	AtomicInt _tail;
+	AtomicInt _head;
+};
+
+} // namespace crown

+ 14 - 0
src/device/input_types.h

@@ -12,6 +12,20 @@ namespace crown
 class InputManager;
 struct InputDevice;
 
+/// Enumerates input device types.
+///
+/// @ingroup Input
+struct InputDeviceType
+{
+	enum Enum
+	{
+		KEYBOARD,
+		MOUSE,
+		TOUCHSCREEN,
+		JOYPAD
+	};
+};
+
 /// Enumerates keyboard buttons.
 ///
 /// @ingroup Input

+ 33 - 14
src/device/main_android.cpp

@@ -8,7 +8,7 @@
 #if CROWN_PLATFORM_ANDROID
 
 #include "device.h"
-#include "os_event_queue.h"
+#include "device_event_queue.h"
 #include "thread.h"
 #include <android/sensor.h>
 #include <android/window.h>
@@ -57,12 +57,10 @@ struct AndroidDevice
 		{
 			s32 num;
 			android_poll_source* source;
-			/*s32 id =*/ ALooper_pollAll(-1, NULL, &num, (void**)&source);
+			ALooper_pollAll(-1, NULL, &num, (void**)&source);
 
-			if (NULL != source)
-			{
+			if (source != NULL)
 				source->process(app, source);
-			}
 		}
 
 		_main_thread.stop();
@@ -83,12 +81,13 @@ struct AndroidDevice
 				// Push metrics here since Android does not trigger APP_CMD_WINDOW_RESIZED
 				const s32 width  = ANativeWindow_getWidth(app->window);
 				const s32 height = ANativeWindow_getHeight(app->window);
-				_queue.push_metrics_event(0, 0, width, height);
+				_queue.push_resolution_event(width, height);
 
 				if (!_main_thread.is_running())
 					_main_thread.start(func, &_margs);
 			}
 			break;
+
 		case APP_CMD_TERM_WINDOW:
 			// The window is being hidden or closed, clean it up.
 			break;
@@ -104,7 +103,7 @@ struct AndroidDevice
 			break;
 
 		case APP_CMD_DESTROY:
-			_queue.push_exit_event(0);
+			_queue.push_exit_event();
 			break;
 		}
 	}
@@ -127,17 +126,29 @@ struct AndroidDevice
 			{
 			case AMOTION_EVENT_ACTION_DOWN:
 			case AMOTION_EVENT_ACTION_POINTER_DOWN:
-				_queue.push_touch_event((s16)x, (s16)y, (u8)pointer_id, true);
+				_queue.push_button_event(InputDeviceType::TOUCHSCREEN
+					, 0
+					, pointer_id
+					, true
+					);
 				break;
 
 			case AMOTION_EVENT_ACTION_UP:
 			case AMOTION_EVENT_ACTION_POINTER_UP:
-				_queue.push_touch_event((s16)x, (s16)y, (u8)pointer_id, false);
+				_queue.push_button_event(InputDeviceType::TOUCHSCREEN
+					, 0
+					, pointer_id
+					, false
+					);
 				break;
 
 			case AMOTION_EVENT_ACTION_OUTSIDE:
 			case AMOTION_EVENT_ACTION_CANCEL:
-				_queue.push_touch_event((s16)x, (s16)y, (u8)pointer_id, false);
+				_queue.push_button_event(InputDeviceType::TOUCHSCREEN
+					, 0
+					, pointer_id
+					, false
+					);
 				break;
 
 			case AMOTION_EVENT_ACTION_MOVE:
@@ -146,7 +157,13 @@ struct AndroidDevice
 					const f32 xx = AMotionEvent_getX(event, index);
 					const f32 yy = AMotionEvent_getY(event, index);
 					const s32 id = AMotionEvent_getPointerId(event, index);
-					_queue.push_touch_event((s16)xx, (s16)yy, (u8)id);
+					_queue.push_axis_event(InputDeviceType::TOUCHSCREEN
+						, 0
+						, id
+						, xx
+						, yy
+						, 0.0f
+						);
 				}
 				break;
 			}
@@ -155,12 +172,14 @@ struct AndroidDevice
 		}
 		else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY)
 		{
-			const s32 keycode = AKeyEvent_getKeyCode(event);
+			const s32 keycode   = AKeyEvent_getKeyCode(event);
 			const s32 keyaction = AKeyEvent_getAction(event);
 
 			if (keycode == AKEYCODE_BACK)
 			{
-				_queue.push_keyboard_event(KeyboardButton::ESCAPE
+				_queue.push_button_event(InputDeviceType::KEYBOARD
+					, 0
+					, KeyboardButton::ESCAPE
 					, keyaction == AKEY_EVENT_ACTION_DOWN ? true : false
 					);
 			}
@@ -183,7 +202,7 @@ struct AndroidDevice
 
 public:
 
-	OsEventQueue _queue;
+	DeviceEventQueue _queue;
 	Thread _main_thread;
 	MainThreadArgs _margs;
 };

+ 41 - 21
src/device/main_linux.cpp

@@ -10,9 +10,9 @@
 #include "array.h"
 #include "command_line.h"
 #include "device.h"
+#include "device_event_queue.h"
 #include "display.h"
 #include "os.h"
-#include "os_event_queue.h"
 #include "thread.h"
 #include "unit_tests.cpp"
 #include "window.h"
@@ -205,7 +205,7 @@ struct Joypad
 		}
 	}
 
-	void update(OsEventQueue& queue)
+	void update(DeviceEventQueue& queue)
 	{
 		JoypadEvent ev;
 		memset(&ev, 0, sizeof(ev));
@@ -216,7 +216,7 @@ struct Joypad
 			const bool connected = fd != -1;
 
 			if (connected != _connected[i])
-				queue.push_joypad_event(i, connected);
+				queue.push_status_event(InputDeviceType::JOYPAD, i, connected);
 
 			_connected[i] = connected;
 
@@ -250,7 +250,8 @@ struct Joypad
 							: 0.0f
 							;
 
-						queue.push_joypad_event(i
+						queue.push_axis_event(InputDeviceType::JOYPAD
+							, i
 							, num > 2 ? 1 : 0
 							, values[0]
 							, -values[1]
@@ -262,7 +263,8 @@ struct Joypad
 				case JS_EVENT_BUTTON:
 					if (ev.number < countof(s_button))
 					{
-						queue.push_joypad_event(i
+						queue.push_button_event(InputDeviceType::JOYPAD
+							, i
 							, s_button[ev.number]
 							, val == 1
 							);
@@ -357,18 +359,22 @@ struct LinuxDevice
 				switch (event.type)
 				{
 				case EnterNotify:
-					_queue.push_mouse_event(event.xcrossing.x, event.xcrossing.y);
+					_queue.push_axis_event(InputDeviceType::MOUSE
+						, 0
+						, MouseAxis::CURSOR
+						, event.xcrossing.x
+						, event.xcrossing.y
+						, 0.0f
+						);
 					break;
 
 				case ClientMessage:
 					if ((Atom)event.xclient.data.l[0] == _wm_delete_message)
-						_queue.push_exit_event(0);
+						_queue.push_exit_event();
 					break;
 
 				case ConfigureNotify:
-					_queue.push_metrics_event(event.xconfigure.x
-						, event.xconfigure.y
-						, event.xconfigure.width
+					_queue.push_resolution_event(event.xconfigure.width
 						, event.xconfigure.height
 						);
 					break;
@@ -378,9 +384,12 @@ struct LinuxDevice
 					{
 						if (event.xbutton.button == Button4 || event.xbutton.button == Button5)
 						{
-							_queue.push_mouse_event(event.xbutton.x
-								, event.xbutton.y
+							_queue.push_axis_event(InputDeviceType::MOUSE
+								, 0
+								, MouseAxis::WHEEL
+								, 0.0f
 								, event.xbutton.button == Button4 ? 1.0f : -1.0f
+								, 0.0f
 								);
 							break;
 						}
@@ -396,8 +405,8 @@ struct LinuxDevice
 
 						if (mb != MouseButton::COUNT)
 						{
-							_queue.push_mouse_event(event.xbutton.x
-								, event.xbutton.y
+							_queue.push_button_event(InputDeviceType::MOUSE
+								, 0
 								, mb
 								, event.type == ButtonPress
 								);
@@ -406,7 +415,13 @@ struct LinuxDevice
 					break;
 
 				case MotionNotify:
-					_queue.push_mouse_event(event.xmotion.x, event.xmotion.y);
+					_queue.push_axis_event(InputDeviceType::MOUSE
+						, 0
+						, MouseAxis::CURSOR
+						, event.xmotion.x
+						, event.xmotion.y
+						, 0.0f
+						);
 					break;
 
 				case KeyPress:
@@ -416,8 +431,13 @@ struct LinuxDevice
 						KeyboardButton::Enum kb = x11_translate_key(keysym);
 
 						if (kb != KeyboardButton::COUNT)
-							_queue.push_keyboard_event(kb, event.type == KeyPress);
-
+						{
+							_queue.push_button_event(InputDeviceType::KEYBOARD
+								, 0
+								, kb
+								, event.type == KeyPress
+								);
+						}
 					}
 					break;
 				case KeymapNotify:
@@ -462,7 +482,7 @@ public:
 	Atom _wm_delete_message;
 	XRRScreenConfiguration* _screen_config;
 	bool _x11_detectable_autorepeat;
-	OsEventQueue _queue;
+	DeviceEventQueue _queue;
 	Joypad _joypad;
 };
 
@@ -742,10 +762,10 @@ int main(int argc, char** argv)
 	CE_UNUSED(m);
 
 	DeviceOptions opts(argc, (const char**)argv);
-	if (opts.parse() == EXIT_SUCCESS)
-		return s_ldvc.run(&opts);
+	if (opts.parse() != EXIT_SUCCESS)
+		return EXIT_FAILURE;
 
-	return EXIT_FAILURE;
+	return s_ldvc.run(&opts);
 }
 
 #endif // CROWN_PLATFORM_LINUX

+ 94 - 25
src/device/main_windows.cpp

@@ -9,7 +9,7 @@
 
 #include "command_line.h"
 #include "device.h"
-#include "os_event_queue.h"
+#include "device_event_queue.h"
 #include "thread.h"
 #include "unit_tests.cpp"
 #include <bgfx/bgfxplatform.h>
@@ -152,7 +152,7 @@ struct Joypad
 		memset(&_connected, 0, sizeof(_connected));
 	}
 
-	void update(OsEventQueue& queue)
+	void update(DeviceEventQueue& queue)
 	{
 		for (u8 i = 0; i < CROWN_MAX_JOYPADS; ++i)
 		{
@@ -163,7 +163,7 @@ struct Joypad
 			const bool connected = result == ERROR_SUCCESS;
 
 			if (connected != _connected[i])
-				queue.push_joypad_event(i, connected);
+				queue.push_status_event(InputDeviceType::JOYPAD, i, connected);
 
 			_connected[i] = connected;
 
@@ -181,7 +181,11 @@ struct Joypad
 					WORD bit = s_xinput_to_joypad[bb].bit;
 					if (bit & diff)
 					{
-						queue.push_joypad_event(i, s_xinput_to_joypad[bb].button, (curr & bit) != 0);
+						queue.push_button_event(InputDeviceType::JOYPAD
+							, i
+							, s_xinput_to_joypad[bb].button
+							, (curr & bit) != 0
+							);
 						gamepad.wButtons = curr;
 					}
 				}
@@ -197,7 +201,13 @@ struct Joypad
 					? f32(value + (value < 0 ? XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE : -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)) / f32(INT16_MAX - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
 					: 0.0f
 					;
-				queue.push_joypad_event(i, JoypadAxis::LEFT, _axis[0].lx, _axis[0].ly, _axis[0].lz);
+				queue.push_axis_event(InputDeviceType::JOYPAD
+					, i
+					, JoypadAxis::LEFT
+					, _axis[0].lx
+					, _axis[0].ly
+					, _axis[0].lz
+					);
 
 				gamepad.sThumbLX = state.Gamepad.sThumbLX;
 			}
@@ -211,7 +221,13 @@ struct Joypad
 					? f32(value + (value < 0 ? XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE : -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)) / f32(INT16_MAX - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
 					: 0.0f
 					;
-				queue.push_joypad_event(i, JoypadAxis::LEFT, _axis[0].lx, _axis[0].ly, _axis[0].lz);
+				queue.push_axis_event(InputDeviceType::JOYPAD
+					, i
+					, JoypadAxis::LEFT
+					, _axis[0].lx
+					, _axis[0].ly
+					, _axis[0].lz
+					);
 
 				gamepad.sThumbLY = state.Gamepad.sThumbLY;
 			}
@@ -224,7 +240,13 @@ struct Joypad
 					? f32(value + (value < 0 ? XINPUT_GAMEPAD_TRIGGER_THRESHOLD : -XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) / f32(UINT8_MAX - XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
 					: 0.0f
 					;
-				queue.push_joypad_event(i, JoypadAxis::LEFT, _axis[0].lx, _axis[0].ly, _axis[0].lz);
+				queue.push_axis_event(InputDeviceType::JOYPAD
+					, i
+					, JoypadAxis::LEFT
+					, _axis[0].lx
+					, _axis[0].ly
+					, _axis[0].lz
+					);
 
 				gamepad.bLeftTrigger = state.Gamepad.bLeftTrigger;
 			}
@@ -238,7 +260,13 @@ struct Joypad
 					? f32(value + (value < 0 ? XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE : -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)) / f32(INT16_MAX - XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
 					: 0.0f
 					;
-				queue.push_joypad_event(i, JoypadAxis::RIGHT, _axis[0].rx, _axis[0].ry, _axis[0].rz);
+				queue.push_axis_event(InputDeviceType::JOYPAD
+					, i
+					, JoypadAxis::RIGHT
+					, _axis[0].rx
+					, _axis[0].ry
+					, _axis[0].rz
+					);
 
 				gamepad.sThumbRX = state.Gamepad.sThumbRX;
 			}
@@ -252,7 +280,13 @@ struct Joypad
 					? f32(value + (value < 0 ? XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE : -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)) / f32(INT16_MAX - XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
 					: 0.0f
 					;
-				queue.push_joypad_event(i, JoypadAxis::RIGHT, _axis[0].rx, _axis[0].ry, _axis[0].rz);
+				queue.push_axis_event(InputDeviceType::JOYPAD
+					, i
+					, JoypadAxis::RIGHT
+					, _axis[0].rx
+					, _axis[0].ry
+					, _axis[0].rz
+					);
 
 				gamepad.sThumbRY = state.Gamepad.sThumbRY;
 			}
@@ -265,7 +299,13 @@ struct Joypad
 					? f32(value + (value < 0 ? XINPUT_GAMEPAD_TRIGGER_THRESHOLD : -XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) / f32(UINT8_MAX - XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
 					: 0.0f
 					;
-				queue.push_joypad_event(i, JoypadAxis::RIGHT, _axis[0].rx, _axis[0].ry, _axis[0].rz);
+				queue.push_axis_event(InputDeviceType::JOYPAD
+					, i
+					, JoypadAxis::RIGHT
+					, _axis[0].rx
+					, _axis[0].ry
+					, _axis[0].rz
+					);
 
 				gamepad.bRightTrigger = state.Gamepad.bRightTrigger;
 			}
@@ -370,14 +410,14 @@ struct WindowsDevice
 		case WM_QUIT:
 		case WM_CLOSE:
 			s_exit = true;
-			_queue.push_exit_event(0);
+			_queue.push_exit_event();
 			return 0;
 
 		case WM_SIZE:
 			{
-				u32 width = GET_X_LPARAM(lparam);
+				u32 width  = GET_X_LPARAM(lparam);
 				u32 height = GET_Y_LPARAM(lparam);
-				_queue.push_metrics_event(0, 0, width, height);
+				_queue.push_resolution_event(width, height);
 			}
 			break;
 
@@ -388,7 +428,7 @@ struct WindowsDevice
 			case SC_RESTORE:
 				{
 					HWND parent = GetWindow(hwnd, GW_OWNER);
-					if (NULL != parent)
+					if (parent != NULL)
 					{
 						PostMessage(parent, id, wparam, lparam);
 					}
@@ -402,7 +442,13 @@ struct WindowsDevice
 				s32 mx = GET_X_LPARAM(lparam);
 				s32 my = GET_Y_LPARAM(lparam);
 				short delta = GET_WHEEL_DELTA_WPARAM(wparam);
-				_queue.push_mouse_event(mx, my, (f32)(delta/WHEEL_DELTA));
+				_queue.push_axis_event(InputDeviceType::MOUSE
+					, 0
+					, MouseAxis::WHEEL
+					, 0.0f
+					, (f32)(delta/WHEEL_DELTA)
+					, 0.0f
+					);
 			}
 			break;
 
@@ -410,7 +456,13 @@ struct WindowsDevice
 			{
 				s32 mx = GET_X_LPARAM(lparam);
 				s32 my = GET_Y_LPARAM(lparam);
-				_queue.push_mouse_event(mx, my);
+				_queue.push_axis_event(InputDeviceType::MOUSE
+					, 0
+					, MouseAxis::CURSOR
+					, mx
+					, my
+					, 0.0f
+					);
 			}
 			break;
 
@@ -419,7 +471,11 @@ struct WindowsDevice
 			{
 				s32 mx = GET_X_LPARAM(lparam);
 				s32 my = GET_Y_LPARAM(lparam);
-				_queue.push_mouse_event(mx, my, MouseButton::LEFT, id == WM_LBUTTONDOWN);
+				_queue.push_button_event(InputDeviceType::MOUSE
+					, 0
+					, MouseButton::LEFT
+					, id == WM_LBUTTONDOWN
+					);
 			}
 			break;
 
@@ -428,7 +484,11 @@ struct WindowsDevice
 			{
 				s32 mx = GET_X_LPARAM(lparam);
 				s32 my = GET_Y_LPARAM(lparam);
-				_queue.push_mouse_event(mx, my, MouseButton::RIGHT, id == WM_RBUTTONDOWN);
+				_queue.push_button_event(InputDeviceType::MOUSE
+					, 0
+					, MouseButton::RIGHT
+					, id == WM_RBUTTONDOWN
+					);
 			}
 			break;
 
@@ -437,7 +497,11 @@ struct WindowsDevice
 			{
 				s32 mx = GET_X_LPARAM(lparam);
 				s32 my = GET_Y_LPARAM(lparam);
-				_queue.push_mouse_event(mx, my, MouseButton::MIDDLE, id == WM_MBUTTONDOWN);
+				_queue.push_button_event(InputDeviceType::MOUSE
+					, 0
+					, MouseButton::MIDDLE
+					, id == WM_MBUTTONDOWN
+					);
 			}
 			break;
 
@@ -449,8 +513,13 @@ struct WindowsDevice
 				KeyboardButton::Enum kb = win_translate_key(wparam & 0xff);
 
 				if (kb != KeyboardButton::COUNT)
-					_queue.push_keyboard_event(kb, (id == WM_KEYDOWN || id == WM_SYSKEYDOWN));
-
+				{
+					_queue.push_button_event(InputDeviceType::KEYBOARD
+						, 0
+						, kb
+						, (id == WM_KEYDOWN || id == WM_SYSKEYDOWN)
+						);
+				}
 			}
 			break;
 
@@ -466,7 +535,7 @@ struct WindowsDevice
 public:
 
 	HWND _hwnd;
-	OsEventQueue _queue;
+	DeviceEventQueue _queue;
 	Joypad _joypad;
 };
 
@@ -648,10 +717,10 @@ int main(int argc, char** argv)
 	CE_UNUSED(err);
 
 	DeviceOptions opts(argc, (const char**)argv);
-	if (opts.parse() == EXIT_SUCCESS)
-		return s_wdvc.run(&opts);
+	if (opts.parse() != EXIT_SUCCESS)
+		return EXIT_FAILURE;
 
-	return EXIT_FAILURE;
+	return s_wdvc.run(&opts);
 }
 
 #endif // CROWN_PLATFORM_WINDOWS

+ 0 - 329
src/device/os_event_queue.h

@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
- * License: https://github.com/taylor001/crown/blob/master/LICENSE
- */
-
-#pragma once
-
-#include "types.h"
-#include "input_types.h"
-#include "math_types.h"
-#include "atomic_int.h"
-
-namespace crown
-{
-struct OsMetricsEvent
-{
-	u16 x;
-	u16 y;
-	u16 width;
-	u16 height;
-};
-
-struct OsExitEvent
-{
-	s32 code;
-};
-
-/// Represents an event fired by mouse.
-struct OsMouseEvent
-{
-	enum Enum
-	{
-		BUTTON,
-		WHEEL,
-		MOVE
-	};
-
-	OsMouseEvent::Enum type;
-	MouseButton::Enum button;
-	s16 x;
-	s16 y;
-	bool pressed;
-	f32 wheel;
-};
-
-/// Represents an event fired by keyboard.
-struct OsKeyboardEvent
-{
-	KeyboardButton::Enum button;
-	bool pressed;
-};
-
-/// Represents an event fired by touch screen.
-struct OsTouchEvent
-{
-	enum Enum
-	{
-		POINTER,
-		MOVE
-	};
-
-	OsTouchEvent::Enum type;
-	u8 pointer_id;
-	s16 x;
-	s16 y;
-	bool pressed;
-};
-
-/// Represents an event fired by joystick
-struct OsJoypadEvent
-{
-	enum Enum
-	{
-		BUTTON,
-		AXIS,
-		CONNECTED
-	};
-
-	OsJoypadEvent::Enum type;
-	u8 index;
-	bool connected;
-	u8 button;
-	bool pressed;
-	f32 x;
-	f32 y;
-	f32 z;
-};
-
-/// Represents an event fired by accelerometer.
-struct OsAccelerometerEvent
-{
-	f32 x;
-	f32 y;
-	f32 z;
-};
-
-struct OsEvent
-{
-	/// Represents an event fired by the OS
-	enum Enum
-	{
-		NONE,
-
-		KEYBOARD,
-		MOUSE,
-		TOUCH,
-		JOYPAD,
-		ACCELEROMETER,
-
-		METRICS,
-		PAUSE,
-		RESUME,
-		// Exit from program
-		EXIT
-	};
-
-	OsEvent::Enum type;
-	union
-	{
-		OsMetricsEvent metrics;
-		OsExitEvent exit;
-		OsMouseEvent mouse;
-		OsKeyboardEvent keyboard;
-		OsTouchEvent touch;
-		OsJoypadEvent joypad;
-		OsAccelerometerEvent accelerometer;
-	};
-};
-
-#define MAX_OS_EVENTS 4096
-
-/// Single Producer Single Consumer event queue.
-/// Used only to pass events from os thread to main thread.
-struct OsEventQueue
-{
-	OsEventQueue()
-		: _tail(0)
-		, _head(0)
-	{
-	}
-
-	void push_mouse_event(u16 x, u16 y)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::MOUSE;
-		ev.mouse.type = OsMouseEvent::MOVE;
-		ev.mouse.x = x;
-		ev.mouse.y = y;
-
-		push_event(ev);
-	}
-
-	void push_mouse_event(s16 x, s16 y, MouseButton::Enum b, bool pressed)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::MOUSE;
-		ev.mouse.type = OsMouseEvent::BUTTON;
-		ev.mouse.x = x;
-		ev.mouse.y = y;
-		ev.mouse.button = b;
-		ev.mouse.pressed = pressed;
-
-		push_event(ev);
-	}
-
-	void push_mouse_event(s16 x, s16 y, f32 wheel)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::MOUSE;
-		ev.mouse.type = OsMouseEvent::WHEEL;
-		ev.mouse.x = x;
-		ev.mouse.y = y;
-		ev.mouse.wheel = wheel;
-
-		push_event(ev);
-	}
-
-	void push_keyboard_event(KeyboardButton::Enum b, bool pressed)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::KEYBOARD;
-		ev.keyboard.button = b;
-		ev.keyboard.pressed = pressed;
-
-		push_event(ev);
-	}
-
-	void push_touch_event(s16 x, s16 y, u8 pointer_id)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::TOUCH;
-		ev.touch.type = OsTouchEvent::MOVE;
-		ev.touch.x = x;
-		ev.touch.y = y;
-		ev.touch.pointer_id = pointer_id;
-
-		push_event(ev);
-	}
-
-	void push_joypad_event(u8 i, bool connected)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::JOYPAD;
-		ev.joypad.type = OsJoypadEvent::CONNECTED;
-		ev.joypad.index = i;
-		ev.joypad.connected = connected;
-
-		push_event(ev);
-	}
-
-	void push_joypad_event(u8 i, u8 button, bool pressed)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::JOYPAD;
-		ev.joypad.type = OsJoypadEvent::BUTTON;
-		ev.joypad.index = i;
-		ev.joypad.button = button;
-		ev.joypad.pressed = pressed;
-
-		push_event(ev);
-	}
-
-	void push_joypad_event(u8 i, u8 axis, f32 x, f32 y, f32 z)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::JOYPAD;
-		ev.joypad.type = OsJoypadEvent::AXIS;
-		ev.joypad.index = i;
-		ev.joypad.button = axis;
-		ev.joypad.x = x;
-		ev.joypad.y = y;
-		ev.joypad.z = z;
-
-		push_event(ev);
-	}
-
-	void push_touch_event(s16 x, s16 y, u8 pointer_id, bool pressed)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::TOUCH;
-		ev.touch.type = OsTouchEvent::POINTER;
-		ev.touch.x = x;
-		ev.touch.y = y;
-		ev.touch.pointer_id = pointer_id;
-		ev.touch.pressed = pressed;
-
-		push_event(ev);
-	}
-
-	void push_exit_event(s32 code)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::EXIT;
-		ev.exit.code = code;
-
-		push_event(ev);
-	}
-
-	void push_pause_event()
-	{
-		OsEvent ev;
-		ev.type = OsEvent::PAUSE;
-		push_event(ev);
-	}
-
-	void push_resume_event()
-	{
-		OsEvent ev;
-		ev.type = OsEvent::RESUME;
-		push_event(ev);
-	}
-
-	void push_metrics_event(u16 x, u16 y, u16 width, u16 height)
-	{
-		OsEvent ev;
-		ev.type = OsEvent::METRICS;
-		ev.metrics.x = x;
-		ev.metrics.y = y;
-		ev.metrics.width = width;
-		ev.metrics.height = height;
-
-		push_event(ev);
-	}
-
-	void push_none_event()
-	{
-		OsEvent ev;
-		ev.type = OsEvent::NONE;
-
-		push_event(ev);
-	}
-
-	bool push_event(const OsEvent& ev)
-	{
-		int cur_tail = _tail.load();
-		int next_tail = increment(cur_tail);
-		if(next_tail != _head.load())
-		{
-			_queue[cur_tail] = ev;
-			_tail.store(next_tail);
-			return true;
-		}
-
-		return false;
-	}
-
-	bool pop_event(OsEvent& ev)
-	{
-		const int cur_head = _head.load();
-		if(cur_head == _tail.load()) return false;
-
-		ev = _queue[cur_head];
-		_head.store(increment(cur_head));
-		return true;
-	}
-
-	int increment(int idx) const
-	{
-	  return (idx + 1) % MAX_OS_EVENTS;
-	}
-
-private:
-
-	OsEvent _queue[MAX_OS_EVENTS];
-	AtomicInt _tail;
-	AtomicInt _head;
-};
-
-} // namespace crown