Parcourir la source

Add initial Display

Daniele Bartolini il y a 10 ans
Parent
commit
6787e0a3fd
8 fichiers modifiés avec 245 ajouts et 98 suppressions
  1. 8 0
      src/device.cpp
  2. 5 0
      src/device.h
  3. 39 0
      src/lua/lua_api.cpp
  4. 38 0
      src/main/display.h
  5. 21 15
      src/main/main_android.cpp
  6. 112 81
      src/main/main_linux.cpp
  7. 21 0
      src/main/main_windows.cpp
  8. 1 2
      src/main/window.h

+ 8 - 0
src/device.cpp

@@ -134,6 +134,7 @@ Device::Device(const DeviceOptions& opts)
 	, _input_manager(NULL)
 	, _unit_manager(NULL)
 	, _lua_environment(NULL)
+	, _display(NULL)
 	, _window(NULL)
 	, _boot_package_id(uint64_t(0))
 	, _boot_script_id(uint64_t(0))
@@ -177,6 +178,7 @@ void Device::init()
 	_bgfx_allocator = CE_NEW(_allocator, BgfxAllocator)(default_allocator());
 	_bgfx_callback  = CE_NEW(_allocator, BgfxCallback)();
 
+	_display = Display::create(_allocator);
 	_window = Window::create(_allocator);
 	_window->open(_device_options.window_x()
 		, _device_options.window_y()
@@ -243,6 +245,7 @@ void Device::shutdown()
 
 	bgfx::shutdown();
 	Window::destroy(_allocator, *_window);
+	Display::destroy(_allocator, *_display);
 	CE_DELETE(_allocator, _bgfx_callback);
 	CE_DELETE(_allocator, _bgfx_allocator);
 
@@ -419,6 +422,11 @@ UnitManager* Device::unit_manager()
 	return _unit_manager;
 }
 
+Display* Device::display()
+{
+	return _display;
+}
+
 Window* Device::window()
 {
 	return _window;

+ 5 - 0
src/device.h

@@ -9,6 +9,7 @@
 #include "config.h"
 #include "container_types.h"
 #include "device_options.h"
+#include "display.h"
 #include "filesystem_types.h"
 #include "input_types.h"
 #include "linear_allocator.h"
@@ -47,6 +48,7 @@ class Device
 	InputManager* _input_manager;
 	UnitManager* _unit_manager;
 	LuaEnvironment* _lua_environment;
+	Display* _display;
 	Window* _window;
 
 	StringId64 _boot_package_id;
@@ -166,6 +168,9 @@ public:
 	/// Returns the unit manager.
 	UnitManager* unit_manager();
 
+	/// Returns the main display.
+	Display* display();
+
 	/// Returns the main window.
 	Window* window();
 

+ 39 - 0
src/lua/lua_api.cpp

@@ -2614,6 +2614,42 @@ static int gui_draw_text(lua_State* L)
 	return 0;
 }
 
+static int display_modes(lua_State* L)
+{
+	LuaStack stack(L);
+	TempAllocator1024 ta;
+	Array<DisplayMode> modes(ta);
+	device()->display()->modes(modes);
+	stack.push_table(array::size(modes));
+	for (uint32_t i = 0; i < array::size(modes); ++i)
+	{
+		stack.push_key_begin(i+1);
+		stack.push_table(3);
+		{
+			stack.push_key_begin("id");
+			stack.push_int(modes[i].id);
+			stack.push_key_end();
+
+			stack.push_key_begin("width");
+			stack.push_int(modes[i].width);
+			stack.push_key_end();
+
+			stack.push_key_begin("height");
+			stack.push_int(modes[i].height);
+			stack.push_key_end();
+		}
+		stack.push_key_end();
+	}
+	return 1;
+}
+
+static int display_set_mode(lua_State* L)
+{
+	LuaStack stack(L);
+	device()->display()->set_mode(stack.get_int(1));
+	return 0;
+}
+
 static int window_show(lua_State* L)
 {
 	LuaStack stack(L);
@@ -3080,6 +3116,9 @@ void load_api(LuaEnvironment& env)
 	env.load_module_function("Gui", "draw_image_uv",  gui_draw_image_uv);
 	env.load_module_function("Gui", "draw_text",      gui_draw_text);
 
+	env.load_module_function("Display", "modes",    display_modes);
+	env.load_module_function("Display", "set_mode", display_set_mode);
+
 	env.load_module_function("Window", "show",      window_show);
 	env.load_module_function("Window", "hide",      window_hide);
 	env.load_module_function("Window", "resize",    window_resize);

+ 38 - 0
src/main/display.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#pragma once
+
+#include "memory_types.h"
+#include "types.h"
+
+namespace crown
+{
+/// Display mode.
+///
+/// @a ingroup Device
+struct DisplayMode
+{
+	uint32_t id;
+	uint32_t width;
+	uint32_t height;
+};
+
+/// Display interface.
+///
+/// @ingroup Device
+class Display
+{
+public:
+
+	/// Opens the window.
+	virtual void modes(Array<DisplayMode>& modes) = 0;
+	virtual void set_mode(uint32_t id) = 0;
+
+	static Display* create(Allocator& a);
+	static void destroy(Allocator& a, Display& d);
+};
+
+} // namespace crown

+ 21 - 15
src/main/main_android.cpp

@@ -27,21 +27,6 @@ extern "C"
 namespace crown
 {
 
-// void display_modes(Array<DisplayMode>& /*modes*/)
-// {
-// 	// Do nothing
-// }
-
-// void set_display_mode(uint32_t /*id*/)
-// {
-// 	// Do nothing
-// }
-
-// void set_fullscreen(bool /*full*/)
-// {
-// 	// Do nothing
-// }
-
 static bool s_exit = false;
 
 struct MainThreadArgs
@@ -281,6 +266,27 @@ void Window::destroy(Allocator& a, Window& w)
 	CE_DELETE(a, &w);
 }
 
+class DisplayAndroid : public Display
+{
+	void modes(Array<DisplayMode>& /*modes*/)
+	{
+	}
+
+	void set_mode(uint32_t /*id*/)
+	{
+	}
+};
+
+Display* Display::create(Allocator& a)
+{
+	return CE_NEW(a, DisplayAndroid)();
+}
+
+void Display::destroy(Allocator& a, Display& d)
+{
+	CE_DELETE(a, &d);
+}
+
 static AndroidDevice s_advc;
 
 bool next_event(OsEvent& ev)

+ 112 - 81
src/main/main_linux.cpp

@@ -11,6 +11,7 @@
 #include "command_line.h"
 #include "console_server.h"
 #include "device.h"
+#include "display.h"
 #include "os_event_queue.h"
 #include "thread.h"
 #include "window.h"
@@ -24,52 +25,6 @@
 
 namespace crown
 {
-
-// void display_modes(Array<DisplayMode>& modes)
-// {
-// 	int num_rrsizes = 0;
-// 	XRRScreenSize* rrsizes = XRRConfigSizes(m_screen_config, &num_rrsizes);
-
-// 	for (int i = 0; i < num_rrsizes; i++)
-// 	{
-// 		DisplayMode dm;
-// 		dm.id = (uint32_t) i;
-// 		dm.width = rrsizes[i].width;
-// 		dm.height = rrsizes[i].height;
-// 		array::push_back(modes, dm);
-// 	}
-// }
-
-// void set_display_mode(uint32_t id)
-// {
-// 	// Check if id is valid
-// 	int num_rrsizes = 0;
-// 	XRRScreenSize* rrsizes = XRRConfigSizes(m_screen_config, &num_rrsizes);
-// 	(void) rrsizes;
-
-// 	if ((int) id >= num_rrsizes)
-// 		return;
-
-// 	XRRSetScreenConfig(s_x11_display,
-// 		m_screen_config,
-// 		RootWindow(s_x11_display, DefaultScreen(s_x11_display)),
-// 		(int) id,
-// 		RR_Rotate_0,
-// 		CurrentTime);
-// }
-
-// void set_fullscreen(bool full)
-// {
-// 	XEvent e;
-// 	e.xclient.type = ClientMessage;
-// 	e.xclient.window = m_x11_window;
-// 	e.xclient.message_type = XInternAtom(s_x11_display, "_NET_WM_STATE", False );
-// 	e.xclient.format = 32;
-// 	e.xclient.data.l[0] = full ? 1 : 0;
-// 	e.xclient.data.l[1] = XInternAtom(s_x11_display, "_NET_WM_STATE_FULLSCREEN", False);
-// 	XSendEvent(s_x11_display, DefaultRootWindow(s_x11_display), False, SubstructureNotifyMask, &e);
-// }
-
 static KeyboardButton::Enum x11_translate_key(KeySym x11_key)
 {
 	switch (x11_key)
@@ -345,12 +300,11 @@ int32_t func(void* data)
 	return EXIT_SUCCESS;
 }
 
-static Display* s_x11_display = NULL;
-
 struct LinuxDevice
 {
 	LinuxDevice()
-		: _screen_config(NULL)
+		: _x11_display(NULL)
+		, _screen_config(NULL)
 		, _x11_detectable_autorepeat(false)
 	{
 	}
@@ -362,19 +316,19 @@ struct LinuxDevice
 		CE_ASSERT(xs != 0, "XInitThreads: error");
 		CE_UNUSED(xs);
 
-		s_x11_display = XOpenDisplay(NULL);
-		CE_ASSERT(s_x11_display != NULL, "XOpenDisplay: error");
+		_x11_display = XOpenDisplay(NULL);
+		CE_ASSERT(_x11_display != NULL, "XOpenDisplay: error");
 
-		::Window root_window = RootWindow(s_x11_display, DefaultScreen(s_x11_display));
+		::Window root_window = RootWindow(_x11_display, DefaultScreen(_x11_display));
 
 		// Do we have detectable autorepeat?
 		Bool detectable;
-		_x11_detectable_autorepeat = (bool)XkbSetDetectableAutoRepeat(s_x11_display, true, &detectable);
+		_x11_detectable_autorepeat = (bool)XkbSetDetectableAutoRepeat(_x11_display, true, &detectable);
 
-		_wm_delete_message = XInternAtom(s_x11_display, "WM_DELETE_WINDOW", False);
+		_wm_delete_message = XInternAtom(_x11_display, "WM_DELETE_WINDOW", False);
 
 		// Save screen configuration
-		_screen_config = XRRGetScreenInfo(s_x11_display, root_window);
+		_screen_config = XRRGetScreenInfo(_x11_display, root_window);
 
 		Rotation rr_old_rot;
 		const SizeID rr_old_sizeid = XRRConfigCurrentConfiguration(_screen_config, &rr_old_rot);
@@ -403,7 +357,7 @@ struct LinuxDevice
 
 		if (rr_rot != rr_old_rot || rr_sizeid != rr_old_sizeid)
 		{
-			XRRSetScreenConfig(s_x11_display
+			XRRSetScreenConfig(_x11_display
 				, _screen_config
 				, root_window
 				, rr_old_sizeid
@@ -413,7 +367,7 @@ struct LinuxDevice
 		}
 		XRRFreeScreenConfigInfo(_screen_config);
 
-		XCloseDisplay(s_x11_display);
+		XCloseDisplay(_x11_display);
 		return EXIT_SUCCESS;
 	}
 
@@ -421,10 +375,10 @@ struct LinuxDevice
 	{
 		_joypad.update(_queue);
 
-		while (XPending(s_x11_display))
+		while (XPending(_x11_display))
 		{
 			XEvent event;
-			XNextEvent(s_x11_display, &event);
+			XNextEvent(_x11_display, &event);
 
 			switch (event.type)
 			{
@@ -512,6 +466,7 @@ struct LinuxDevice
 
 public:
 
+	::Display* _x11_display;
 	Atom _wm_delete_message;
 	XRRScreenConfiguration* _screen_config;
 	bool _x11_detectable_autorepeat;
@@ -519,8 +474,11 @@ public:
 	Joypad _joypad;
 };
 
+static LinuxDevice s_ldvc;
+
 class WindowX11 : public Window
 {
+	::Display* _x11_display;
 	::Window _x11_window;
 	Cursor _x11_hidden_cursor;
 	Atom _wm_delete_message;
@@ -528,18 +486,20 @@ class WindowX11 : public Window
 public:
 
 	WindowX11()
-		: _x11_window(None)
+		: _x11_display(NULL)
+		, _x11_window(None)
 		, _x11_hidden_cursor(None)
 	{
+		_x11_display = s_ldvc._x11_display;
 	}
 
 	void open(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t parent)
 	{
-		int screen = DefaultScreen(s_x11_display);
-		int depth = DefaultDepth(s_x11_display, screen);
-		Visual* visual = DefaultVisual(s_x11_display, screen);
+		int screen = DefaultScreen(_x11_display);
+		int depth = DefaultDepth(_x11_display, screen);
+		Visual* visual = DefaultVisual(_x11_display, screen);
 
-		::Window root_window = RootWindow(s_x11_display, screen);
+		::Window root_window = RootWindow(_x11_display, screen);
 		::Window parent_window = (parent == 0) ? root_window : (::Window)parent;
 
 		// Create main window
@@ -561,7 +521,7 @@ public:
 				;
 		}
 
-		_x11_window = XCreateWindow(s_x11_display
+		_x11_window = XCreateWindow(_x11_display
 			, parent_window
 			, x
 			, y
@@ -582,45 +542,45 @@ public:
 		Colormap colormap;
 		static char no_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
-		colormap = XDefaultColormap(s_x11_display, screen);
-		XAllocNamedColor(s_x11_display, colormap, "black", &black, &dummy);
-		bm_no = XCreateBitmapFromData(s_x11_display, _x11_window, no_data, 8, 8);
-		_x11_hidden_cursor = XCreatePixmapCursor(s_x11_display, bm_no, bm_no, &black, &black, 0, 0);
+		colormap = XDefaultColormap(_x11_display, screen);
+		XAllocNamedColor(_x11_display, colormap, "black", &black, &dummy);
+		bm_no = XCreateBitmapFromData(_x11_display, _x11_window, no_data, 8, 8);
+		_x11_hidden_cursor = XCreatePixmapCursor(_x11_display, bm_no, bm_no, &black, &black, 0, 0);
 
-		_wm_delete_message = XInternAtom(s_x11_display, "WM_DELETE_WINDOW", False);
-		XSetWMProtocols(s_x11_display, _x11_window, &_wm_delete_message, 1);
+		_wm_delete_message = XInternAtom(_x11_display, "WM_DELETE_WINDOW", False);
+		XSetWMProtocols(_x11_display, _x11_window, &_wm_delete_message, 1);
 
-		XMapRaised(s_x11_display, _x11_window);
+		XMapRaised(_x11_display, _x11_window);
 	}
 
 	void close()
 	{
-		XDestroyWindow(s_x11_display, _x11_window);
+		XDestroyWindow(_x11_display, _x11_window);
 	}
 
 	void bgfx_setup()
 	{
-		bgfx::x11SetDisplayWindow(s_x11_display, _x11_window);
+		bgfx::x11SetDisplayWindow(_x11_display, _x11_window);
 	}
 
 	void show()
 	{
-		XMapRaised(s_x11_display, _x11_window);
+		XMapRaised(_x11_display, _x11_window);
 	}
 
 	void hide()
 	{
-		XUnmapWindow(s_x11_display, _x11_window);
+		XUnmapWindow(_x11_display, _x11_window);
 	}
 
 	void resize(uint16_t width, uint16_t height)
 	{
-		XResizeWindow(s_x11_display, _x11_window, width, height);
+		XResizeWindow(_x11_display, _x11_window, width, height);
 	}
 
 	void move(uint16_t x, uint16_t y)
 	{
-		XMoveWindow(s_x11_display, _x11_window, x, y);
+		XMoveWindow(_x11_display, _x11_window, x, y);
 	}
 
 	void minimize()
@@ -636,7 +596,7 @@ public:
 		static char buf[512];
 		memset(buf, 0, sizeof(buf));
 		char* name;
-		XFetchName(s_x11_display, _x11_window, &name);
+		XFetchName(_x11_display, _x11_window, &name);
 		strncpy(buf, name, sizeof(buf));
 		XFree(name);
 		return buf;
@@ -644,7 +604,7 @@ public:
 
 	void set_title (const char* title)
 	{
-		XStoreName(s_x11_display, _x11_window, title);
+		XStoreName(_x11_display, _x11_window, title);
 	}
 
 	void* handle()
@@ -663,7 +623,78 @@ void Window::destroy(Allocator& a, Window& w)
 	CE_DELETE(a, &w);
 }
 
-static LinuxDevice s_ldvc;
+class DisplayXRandr : public Display
+{
+	::Display* _x11_display;
+	XRRScreenConfiguration* _screen_config;
+
+public:
+
+	DisplayXRandr()
+		: _x11_display(NULL)
+		, _screen_config(NULL)
+	{
+		_x11_display = s_ldvc._x11_display;
+		_screen_config = s_ldvc._screen_config;
+	}
+
+	void modes(Array<DisplayMode>& modes)
+	{
+		int num = 0;
+		XRRScreenSize* sizes = XRRConfigSizes(_screen_config, &num);
+
+		if (!sizes)
+			return;
+
+		for (int i = 0; i < num; ++i)
+		{
+			DisplayMode dm;
+			dm.id     = (uint32_t)i;
+			dm.width  = sizes[i].width;
+			dm.height = sizes[i].height;
+			array::push_back(modes, dm);
+		}
+	}
+
+	void set_mode(uint32_t id)
+	{
+		int num = 0;
+		XRRScreenSize* sizes = XRRConfigSizes(_screen_config, &num);
+
+		if (!sizes || (int)id >= num)
+			return;
+
+		XRRSetScreenConfig(_x11_display
+			, _screen_config
+			, RootWindow(_x11_display, DefaultScreen(_x11_display))
+			, (int)id
+			, RR_Rotate_0
+			, CurrentTime
+			);
+	}
+
+	// void set_fullscreen(bool full)
+	// {
+	// 	XEvent e;
+	// 	e.xclient.type = ClientMessage;
+	// 	e.xclient.window = m_x11_window;
+	// 	e.xclient.message_type = XInternAtom(_x11_display, "_NET_WM_STATE", False );
+	// 	e.xclient.format = 32;
+	// 	e.xclient.data.l[0] = full ? 1 : 0;
+	// 	e.xclient.data.l[1] = XInternAtom(_x11_display, "_NET_WM_STATE_FULLSCREEN", False);
+	// 	XSendEvent(_x11_display, DefaultRootWindow(_x11_display), False, SubstructureNotifyMask, &e);
+	// }
+};
+
+Display* Display::create(Allocator& a)
+{
+	return CE_NEW(a, DisplayXRandr)();
+}
+
+void Display::destroy(Allocator& a, Display& d)
+{
+	CE_DELETE(a, &d);
+}
 
 bool next_event(OsEvent& ev)
 {

+ 21 - 0
src/main/main_windows.cpp

@@ -567,6 +567,27 @@ void Window::destroy(Allocator& a, Window& w)
 	CE_DELETE(a, &w);
 }
 
+class DisplayWin : public Display
+{
+	void modes(Array<DisplayMode>& /*modes*/)
+	{
+	}
+
+	void set_mode(uint32_t /*id*/)
+	{
+	}
+};
+
+Display* Display::create(Allocator& a)
+{
+	return CE_NEW(a, DisplayWin)();
+}
+
+void Display::destroy(Allocator& a, Display& d)
+{
+	CE_DELETE(a, &d);
+}
+
 bool next_event(OsEvent& ev)
 {
 	return s_wdvc._queue.pop_event(ev);

+ 1 - 2
src/main/window.h

@@ -10,8 +10,7 @@
 
 namespace crown
 {
-
-/// Window
+/// Window interface.
 ///
 /// @ingroup Device
 class Window