forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			603 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			603 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | #include <Kore/Graphics4/Graphics.h>
 | ||
|  | #include <Kore/Input/Keyboard.h>
 | ||
|  | #include <Kore/Input/Mouse.h>
 | ||
|  | #include <Kore/Log.h>
 | ||
|  | #include <Kore/System.h>
 | ||
|  | 
 | ||
|  | #include "Display.h"
 | ||
|  | 
 | ||
|  | #include <assert.h>
 | ||
|  | #include <cstring>
 | ||
|  | 
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | 
 | ||
|  | #include <Kore/ogl.h>
 | ||
|  | 
 | ||
|  | #include <bcm_host.h>
 | ||
|  | 
 | ||
|  | #include <fcntl.h>
 | ||
|  | #include <inttypes.h>
 | ||
|  | #include <linux/input.h>
 | ||
|  | 
 | ||
|  | #include <X11/Xlib.h>
 | ||
|  | 
 | ||
|  | // apt-get install libx11-dev
 | ||
|  | 
 | ||
|  | namespace { | ||
|  | 	// static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_STENCIL_SIZE, 8, None};
 | ||
|  | 	// static int dblBuf[]  = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_STENCIL_SIZE, 8, GLX_DOUBLEBUFFER, None};
 | ||
|  | 
 | ||
|  | 	uint32_t screen_width; | ||
|  | 	uint32_t screen_height; | ||
|  | 	Kore::WindowMode windowMode; | ||
|  | 	uint32_t width; | ||
|  | 	uint32_t height; | ||
|  | 	bool bcmHostStarted = false; | ||
|  | 
 | ||
|  | 	EGLDisplay display; | ||
|  | 	EGLSurface surface; | ||
|  | 	EGLContext context; | ||
|  | 
 | ||
|  | 	DISPMANX_ELEMENT_HANDLE_T dispman_element; | ||
|  | 
 | ||
|  | 	GLboolean doubleBuffer = GL_TRUE; | ||
|  | 
 | ||
|  | 	void fatalError(const char *message) { | ||
|  | 		printf("main: %s\n", message); | ||
|  | 		exit(1); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	int getbit(uint32_t *bits, uint32_t bit) { | ||
|  | 		return (bits[bit / 32] >> (bit % 32)) & 1; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void enable_bit(uint32_t *bits, uint32_t bit) { | ||
|  | 		bits[bit / 32] |= 1u << (bit % 32); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void disable_bit(uint32_t *bits, uint32_t bit) { | ||
|  | 		bits[bit / 32] &= ~(1u << (bit % 32)); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void set_bit(uint32_t *bits, uint32_t bit, int value) { | ||
|  | 		if (value) | ||
|  | 			enable_bit(bits, bit); | ||
|  | 		else | ||
|  | 			disable_bit(bits, bit); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	struct InputDevice { | ||
|  | 		int fd; | ||
|  | 		uint16_t keys; | ||
|  | 		uint32_t key_state[(KEY_MAX - 1) / 32 + 1]; | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	const int inputDevicesCount = 16; | ||
|  | 	InputDevice inputDevices[inputDevicesCount]; | ||
|  | 
 | ||
|  | 	Display *dpy; | ||
|  | 
 | ||
|  | 	void openXWindow(int x, int y, int width, int height) { | ||
|  | 		dpy = XOpenDisplay(NULL); | ||
|  | 		XSetWindowAttributes winAttr; | ||
|  | 		winAttr.event_mask = StructureNotifyMask; | ||
|  | 		Window w = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, width, height, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWEventMask, &winAttr); | ||
|  | 		XMapWindow(dpy, w); | ||
|  | 		XFlush(dpy); | ||
|  | 
 | ||
|  | 		// TODO: Figure this out
 | ||
|  | 		/*Atom atom = XInternAtom(dpy, "_NET_FRAME_EXTENTS", True);
 | ||
|  | 		Atom atom2; | ||
|  | 		int f; | ||
|  | 		unsigned long n, b; | ||
|  | 		XEvent e; | ||
|  | 		unsigned char *data = 0; | ||
|  | 		while (XGetWindowProperty(dpy, w, atom, | ||
|  | 		           0, 4, False, AnyPropertyType, | ||
|  | 		           &atom2, &f, | ||
|  | 		           &n, &b, &data) != Success || n != 4 || b != 0) { | ||
|  | 		    XNextEvent(dpy, &e); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		long* extents = (long*) data; | ||
|  | 		//printf ("Got frame extents: left %ld right %ld top %ld bottom %ld\n",
 | ||
|  | 		//    extents[0], extents[1], extents[2], extents[3]);
 | ||
|  | 		*/ | ||
|  | 
 | ||
|  | 		XMoveWindow(dpy, w, x - 1, y - 30); // extents[2]);
 | ||
|  | 		XFlush(dpy); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void setScreenSize() { | ||
|  | 		if (!bcmHostStarted) { | ||
|  | 			bcm_host_init(); | ||
|  | 			bcmHostStarted = true; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (screen_width == 0 || screen_height == 0) { | ||
|  | 			int32_t success = 0; | ||
|  | 			success = graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height); | ||
|  | 			assert(success >= 0); | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | namespace Kore { | ||
|  | 	namespace Display { | ||
|  | 		void enumDisplayMonitors(DeviceInfo screens[], int &displayCounter) { | ||
|  | 			displayCounter = 1; | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void Kore::System::setup() {} | ||
|  | 
 | ||
|  | bool Kore::System::isFullscreen() { | ||
|  | 	// TODO (DK)
 | ||
|  | 	return false; | ||
|  | } | ||
|  | 
 | ||
|  | // TODO (DK) the whole glx stuff should go into Graphics/OpenGL?
 | ||
|  | //  -then there would be a better separation between window + context setup
 | ||
|  | int createWindow(const char *title, int x, int y, int width, int height, Kore::WindowMode windowMode, int targetDisplay, int depthBufferBits, | ||
|  |                  int stencilBufferBits) { | ||
|  | 	if (!bcmHostStarted) { | ||
|  | 		bcm_host_init(); | ||
|  | 		bcmHostStarted = true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	::windowMode = windowMode; | ||
|  | 	::width = width; | ||
|  | 	::height = height; | ||
|  | 	// uint32_t screen_width = 640;
 | ||
|  | 	// uint32_t screen_height = 480;
 | ||
|  | 
 | ||
|  | 	EGLBoolean result; | ||
|  | 	EGLint num_config; | ||
|  | 
 | ||
|  | 	static EGL_DISPMANX_WINDOW_T nativewindow; | ||
|  | 
 | ||
|  | 	DISPMANX_DISPLAY_HANDLE_T dispman_display; | ||
|  | 	DISPMANX_UPDATE_HANDLE_T dispman_update; | ||
|  | 	VC_RECT_T dst_rect; | ||
|  | 	VC_RECT_T src_rect; | ||
|  | 
 | ||
|  | 	static const EGLint attribute_list[] = {EGL_RED_SIZE,   8,       EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, | ||
|  | 	                                        EGL_WINDOW_BIT, EGL_NONE}; | ||
|  | 
 | ||
|  | 	static const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; | ||
|  | 	EGLConfig config; | ||
|  | 
 | ||
|  | 	display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | ||
|  | 	assert(display != EGL_NO_DISPLAY); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	result = eglInitialize(display, NULL, NULL); | ||
|  | 	assert(EGL_FALSE != result); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	result = eglChooseConfig(display, attribute_list, &config, 1, &num_config); | ||
|  | 	assert(EGL_FALSE != result); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	result = eglBindAPI(EGL_OPENGL_ES_API); | ||
|  | 	assert(EGL_FALSE != result); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes); | ||
|  | 	assert(context != EGL_NO_CONTEXT); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	setScreenSize(); | ||
|  | 
 | ||
|  | 	if (windowMode == Kore::WindowModeFullscreen) { | ||
|  | 		dst_rect.x = 0; | ||
|  | 		dst_rect.y = 0; | ||
|  | 		dst_rect.width = screen_width; | ||
|  | 		dst_rect.height = screen_height; | ||
|  | 		src_rect.x = 0; | ||
|  | 		src_rect.y = 0; | ||
|  | 		src_rect.width = screen_width << 16; | ||
|  | 		src_rect.height = screen_height << 16; | ||
|  | 	} | ||
|  | 	else { | ||
|  | 		dst_rect.x = x; | ||
|  | 		dst_rect.y = y; | ||
|  | #ifdef KINC_RASPBERRY_PI_SCALING
 | ||
|  | 		dst_rect.width = screen_width; | ||
|  | 		dst_rect.height = screen_height; | ||
|  | #else
 | ||
|  | 		dst_rect.width = width; | ||
|  | 		dst_rect.height = height; | ||
|  | #endif
 | ||
|  | 		src_rect.x = 0; | ||
|  | 		src_rect.y = 0; | ||
|  | 		src_rect.width = width << 16; | ||
|  | 		src_rect.height = height << 16; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	dispman_display = vc_dispmanx_display_open(0 /* LCD */); | ||
|  | 	dispman_update = vc_dispmanx_update_start(0); | ||
|  | 
 | ||
|  | 	VC_DISPMANX_ALPHA_T alpha = {}; | ||
|  | 	alpha.flags = (DISPMANX_FLAGS_ALPHA_T)(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS); | ||
|  | 	alpha.opacity = 255; | ||
|  | 	alpha.mask = 0; | ||
|  | 
 | ||
|  | 	dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, | ||
|  | 	                                          0 /*clamp*/, (DISPMANX_TRANSFORM_T)0 /*transform*/); | ||
|  | 
 | ||
|  | 	nativewindow.element = dispman_element; | ||
|  | 	if (windowMode == Kore::WindowModeFullscreen) { | ||
|  | 		nativewindow.width = screen_width; | ||
|  | 		nativewindow.height = screen_height; | ||
|  | 	} | ||
|  | 	else { | ||
|  | 		nativewindow.width = width; | ||
|  | 		nativewindow.height = height; | ||
|  | #ifndef KINC_RASPBERRY_PI_SCALING
 | ||
|  | 		openXWindow(x, y, width, height); | ||
|  | #endif
 | ||
|  | 	} | ||
|  | 	vc_dispmanx_update_submit_sync(dispman_update); | ||
|  | 
 | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	surface = eglCreateWindowSurface(display, config, &nativewindow, NULL); | ||
|  | 	assert(surface != EGL_NO_SURFACE); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	result = eglMakeCurrent(display, surface, surface, context); | ||
|  | 	assert(EGL_FALSE != result); | ||
|  | 	glCheckErrors(); | ||
|  | 
 | ||
|  | 	// input
 | ||
|  | 
 | ||
|  | 	char name[64]; | ||
|  | 	for (int i = 0; i < inputDevicesCount; ++i) { | ||
|  | 		sprintf(name, "/dev/input/event%d", i); | ||
|  | 
 | ||
|  | 		// PIGU_device_info_t info;
 | ||
|  | 		// if(PIGU_detect_device(name, &info) < 0)
 | ||
|  | 
 | ||
|  | 		uint32_t events[(KEY_MAX - 1) / 32 + 1]; | ||
|  | 
 | ||
|  | 		inputDevices[i].fd = open(name, O_RDONLY | O_NONBLOCK); | ||
|  | 
 | ||
|  | 		if (inputDevices[i].fd < 0) | ||
|  | 			continue; | ||
|  | 
 | ||
|  | 		char deviceName[128]; | ||
|  | 		ioctl(inputDevices[i].fd, EVIOCGNAME(sizeof(deviceName)), deviceName); | ||
|  | 
 | ||
|  | 		printf("Found a device. %s\n", deviceName); | ||
|  | 
 | ||
|  | 		uint32_t types[EV_MAX]; | ||
|  | 		memset(types, 0, sizeof(types)); | ||
|  | 		ioctl(inputDevices[i].fd, EVIOCGBIT(0, EV_MAX), types); | ||
|  | 		int keycount = 0; | ||
|  | 
 | ||
|  | 		if (getbit(types, EV_KEY)) { | ||
|  | 			// count events
 | ||
|  | 			memset(events, 0, sizeof(events)); | ||
|  | 			ioctl(inputDevices[i].fd, EVIOCGBIT(EV_KEY, KEY_MAX), events); | ||
|  | 			int j = 0; | ||
|  | 			for (; j < BTN_MISC; ++j) | ||
|  | 				if (getbit(events, j)) | ||
|  | 					keycount++; | ||
|  | 
 | ||
|  | 			/*j = BTN_MOUSE; // skip misc buttons
 | ||
|  | 
 | ||
|  | 			for(;j<BTN_JOYSTICK;++j) | ||
|  | 		   if(PIGU_get_bit(events, j)) | ||
|  | 		   { | ||
|  | 			  mouse_button_count++; | ||
|  | 			  if(j-BTN_MOUSE>=16) | ||
|  | 			     continue; | ||
|  | 			  buttons.map[buttons.count] = j-BTN_MOUSE; | ||
|  | 			  buttons.count++; | ||
|  | 		   } | ||
|  | 
 | ||
|  | 			for(;j<BTN_GAMEPAD;++j) | ||
|  | 		   if(PIGU_get_bit(events, j)) | ||
|  | 		   { | ||
|  | 			  joystick_button_count++; | ||
|  | 			  if(j-BTN_JOYSTICK>=16) | ||
|  | 			     continue; | ||
|  | 			  buttons.map[buttons.count] = j-BTN_JOYSTICK; | ||
|  | 			  buttons.count++; | ||
|  | 		   } | ||
|  | 
 | ||
|  | 			for(;j<BTN_DIGI;++j) | ||
|  | 		   if(PIGU_get_bit(events, j)) | ||
|  | 		   { | ||
|  | 			  gamepad_button_count++; | ||
|  | 			  if(j-BTN_GAMEPAD>=16) | ||
|  | 			     continue; | ||
|  | 			  buttons.map[buttons.count] = j-BTN_GAMEPAD; | ||
|  | 			  buttons.count++; | ||
|  | 		   }*/ | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | namespace Kore { | ||
|  | 	namespace System { | ||
|  | 		int windowCount() { | ||
|  | 			return 1; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		int windowWidth(int id) { | ||
|  | 			if (windowMode == Kore::WindowModeFullscreen) { | ||
|  | 				return screen_width; | ||
|  | 			} | ||
|  | 			else { | ||
|  | 				return width; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		int windowHeight(int id) { | ||
|  | 			if (windowMode == Kore::WindowModeFullscreen) { | ||
|  | 				return screen_height; | ||
|  | 			} | ||
|  | 			else { | ||
|  | 				return height; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		int desktopWidth() { | ||
|  | 			setScreenSize(); | ||
|  | 			return screen_width; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		int desktopHeight() { | ||
|  | 			setScreenSize(); | ||
|  | 			return screen_height; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		int initWindow(WindowOptions options) { | ||
|  | 			char buffer[1024] = {0}; | ||
|  | 			strcat(buffer, name()); | ||
|  | 			if (options.title != nullptr) { | ||
|  | 				strcat(buffer, options.title); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			int id = createWindow(buffer, options.x == -1 ? screen_width / 2 - options.width / 2 : options.x, | ||
|  | 			                      options.y == -1 ? screen_height / 2 - options.height / 2 : options.y, options.width, options.height, options.mode, | ||
|  | 			                      options.targetDisplay, options.rendererOptions.depthBufferBits, options.rendererOptions.stencilBufferBits); | ||
|  | 			Graphics4::init(id, options.rendererOptions.depthBufferBits, options.rendererOptions.stencilBufferBits); | ||
|  | 			return id; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		void *windowHandle(int id) { | ||
|  | 			return nullptr; | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | namespace Kore { | ||
|  | 	namespace System { | ||
|  | 		int currentDeviceId = -1; | ||
|  | 
 | ||
|  | 		int currentDevice() { | ||
|  | 			return currentDeviceId; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		void setCurrentDevice(int id) { | ||
|  | 			currentDeviceId = id; | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | bool Kore::System::handleMessages() { | ||
|  | 	for (int i = 0; i < inputDevicesCount; ++i) { | ||
|  | 
 | ||
|  | 		int eventcount = 0; | ||
|  | 
 | ||
|  | 		if (inputDevices[i].fd < 0) | ||
|  | 			continue; | ||
|  | 
 | ||
|  | 		input_event event; | ||
|  | 		ssize_t readsize = read(inputDevices[i].fd, &event, sizeof(event)); | ||
|  | 		while (readsize >= 0) { | ||
|  | 
 | ||
|  | 			set_bit(inputDevices[i].key_state, event.code, event.value); | ||
|  | 
 | ||
|  | #define KEY(linuxkey, korekey, keychar)                                                                                                                        \
 | ||
|  | 	case linuxkey:                                                                                                                                             \ | ||
|  | 		if (event.value == 1)                                                                                                                                  \ | ||
|  | 			Kore::Keyboard::the()->_keydown(korekey);                                                                                                          \ | ||
|  | 		else if (event.value == 0)                                                                                                                             \ | ||
|  | 			Kore::Keyboard::the()->_keyup(korekey);                                                                                                            \ | ||
|  | 		break; | ||
|  | 			switch (event.code) { | ||
|  | 				KEY(KEY_RIGHT, KeyRight, ' ') | ||
|  | 				KEY(KEY_LEFT, KeyLeft, ' ') | ||
|  | 				KEY(KEY_UP, KeyUp, ' ') | ||
|  | 				KEY(KEY_DOWN, KeyDown, ' ') | ||
|  | 				KEY(KEY_SPACE, KeySpace, ' ') | ||
|  | 				KEY(KEY_BACKSPACE, KeyBackspace, ' ') | ||
|  | 				KEY(KEY_TAB, KeyTab, ' ') | ||
|  | 				// KEY(KEY_ENTER, KeyEnter, ' ')
 | ||
|  | 				KEY(KEY_LEFTSHIFT, KeyShift, ' ') | ||
|  | 				KEY(KEY_RIGHTSHIFT, KeyShift, ' ') | ||
|  | 				KEY(KEY_LEFTCTRL, KeyControl, ' ') | ||
|  | 				KEY(KEY_RIGHTCTRL, KeyControl, ' ') | ||
|  | 				KEY(KEY_LEFTALT, KeyAlt, ' ') | ||
|  | 				KEY(KEY_RIGHTALT, KeyAlt, ' ') | ||
|  | 				KEY(KEY_DELETE, KeyDelete, ' ') | ||
|  | 				KEY(KEY_A, KeyA, 'a') | ||
|  | 				KEY(KEY_B, KeyB, 'b') | ||
|  | 				KEY(KEY_C, KeyC, 'c') | ||
|  | 				KEY(KEY_D, KeyD, 'd') | ||
|  | 				KEY(KEY_E, KeyE, 'e') | ||
|  | 				KEY(KEY_F, KeyF, 'f') | ||
|  | 				KEY(KEY_G, KeyG, 'g') | ||
|  | 				KEY(KEY_H, KeyH, 'h') | ||
|  | 				KEY(KEY_I, KeyI, 'i') | ||
|  | 				KEY(KEY_J, KeyJ, 'j') | ||
|  | 				KEY(KEY_K, KeyK, 'k') | ||
|  | 				KEY(KEY_L, KeyL, 'l') | ||
|  | 				KEY(KEY_M, KeyM, 'm') | ||
|  | 				KEY(KEY_N, KeyN, 'n') | ||
|  | 				KEY(KEY_O, KeyO, 'o') | ||
|  | 				KEY(KEY_P, KeyP, 'p') | ||
|  | 				KEY(KEY_Q, KeyQ, 'q') | ||
|  | 				KEY(KEY_R, KeyR, 'r') | ||
|  | 				KEY(KEY_S, KeyS, 's') | ||
|  | 				KEY(KEY_T, KeyT, 't') | ||
|  | 				KEY(KEY_U, KeyU, 'u') | ||
|  | 				KEY(KEY_V, KeyV, 'v') | ||
|  | 				KEY(KEY_W, KeyW, 'w') | ||
|  | 				KEY(KEY_X, KeyX, 'x') | ||
|  | 				KEY(KEY_Y, KeyY, 'y') | ||
|  | 				KEY(KEY_Z, KeyZ, 'z') | ||
|  | 				KEY(KEY_1, Key1, '1') | ||
|  | 				KEY(KEY_2, Key2, '2') | ||
|  | 				KEY(KEY_3, Key3, '3') | ||
|  | 				KEY(KEY_4, Key4, '4') | ||
|  | 				KEY(KEY_5, Key5, '5') | ||
|  | 				KEY(KEY_6, Key6, '6') | ||
|  | 				KEY(KEY_7, Key7, '7') | ||
|  | 				KEY(KEY_8, Key8, '8') | ||
|  | 				KEY(KEY_9, Key9, '9') | ||
|  | 				KEY(KEY_0, Key0, '0') | ||
|  | 			} | ||
|  | #undef KEY
 | ||
|  | 
 | ||
|  | 			// printf("Code %d Value %d\n", event.code, event.value);
 | ||
|  | 			readsize = read(inputDevices[i].fd, &event, sizeof(event)); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | #ifndef KINC_RASPBERRY_PI_SCALING
 | ||
|  | 	if (windowMode != Kore::WindowModeFullscreen) { | ||
|  | 		while (XPending(dpy) > 0) { | ||
|  | 			XEvent event; | ||
|  | 			XNextEvent(dpy, &event); | ||
|  | 			printf("Got an X event.\n"); | ||
|  | 			switch (event.type) { | ||
|  | 			case ConfigureNotify: | ||
|  | 				DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); | ||
|  | 
 | ||
|  | 				VC_RECT_T dst_rect; | ||
|  | 				VC_RECT_T src_rect; | ||
|  | 				dst_rect.x = event.xconfigure.x; | ||
|  | 				dst_rect.y = event.xconfigure.y; | ||
|  | 				dst_rect.width = width; | ||
|  | 				dst_rect.height = height; | ||
|  | 				src_rect.x = 0; | ||
|  | 				src_rect.y = 0; | ||
|  | 				src_rect.width = width << 16; | ||
|  | 				src_rect.height = height << 16; | ||
|  | 
 | ||
|  | 				vc_dispmanx_element_change_attributes(update, dispman_element, 0, 0, 255, &dst_rect, &src_rect, 0, (DISPMANX_TRANSFORM_T)0); | ||
|  | 				vc_dispmanx_update_submit_sync(update); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 	return true; | ||
|  | } | ||
|  | 
 | ||
|  | const char *Kore::System::systemId() { | ||
|  | 	return "Pi"; | ||
|  | } | ||
|  | 
 | ||
|  | void Kore::System::makeCurrent(int contextId) { | ||
|  | 	if (currentDeviceId == contextId) { | ||
|  | 		return; | ||
|  | 	} | ||
|  | 
 | ||
|  | #if !defined(NDEBUG)
 | ||
|  | // log(Info, "Kore/System | context switch from %i to %i", currentDeviceId, contextId);
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 	currentDeviceId = contextId; | ||
|  | } | ||
|  | 
 | ||
|  | void Kore::Graphics4::clearCurrent() {} | ||
|  | 
 | ||
|  | void Kore::System::clearCurrent() { | ||
|  | #if !defined(NDEBUG)
 | ||
|  | // log(Info, "Kore/System | context clear");
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 	currentDeviceId = -1; | ||
|  | 	Graphics4::clearCurrent(); | ||
|  | } | ||
|  | 
 | ||
|  | void Kore::System::swapBuffers(int contextId) { | ||
|  | 	eglSwapBuffers(display, surface); | ||
|  | } | ||
|  | 
 | ||
|  | void Kore::System::destroyWindow(int id) { | ||
|  | 	// TODO (DK) implement me
 | ||
|  | } | ||
|  | 
 | ||
|  | void Kore::System::changeResolution(int width, int height, bool fullscreen) {} | ||
|  | 
 | ||
|  | void Kore::System::setTitle(const char *title) {} | ||
|  | 
 | ||
|  | void Kore::System::setKeepScreenOn(bool on) {} | ||
|  | 
 | ||
|  | void Kore::System::showWindow() {} | ||
|  | 
 | ||
|  | void Kore::System::showKeyboard() {} | ||
|  | 
 | ||
|  | void Kore::System::hideKeyboard() {} | ||
|  | 
 | ||
|  | void Kore::System::loadURL(const char *url) {} | ||
|  | 
 | ||
|  | void Kore::System::vibrate(int ms) {} | ||
|  | 
 | ||
|  | const char *Kore::System::language() { | ||
|  | 	return "en"; | ||
|  | } | ||
|  | 
 | ||
|  | namespace { | ||
|  | 	char save[2000]; | ||
|  | 	bool saveInitialized = false; | ||
|  | } | ||
|  | 
 | ||
|  | const char *Kore::System::savePath() { | ||
|  | 	if (!saveInitialized) { | ||
|  | 		strcpy(save, "Ķ~/."); | ||
|  | 		strcat(save, name()); | ||
|  | 		strcat(save, "/"); | ||
|  | 		saveInitialized = true; | ||
|  | 	} | ||
|  | 	return save; | ||
|  | } | ||
|  | 
 | ||
|  | namespace { | ||
|  | 	const char *videoFormats[] = {"ogv", nullptr}; | ||
|  | } | ||
|  | 
 | ||
|  | const char **Kore::System::videoFormats() { | ||
|  | 	return ::videoFormats; | ||
|  | } | ||
|  | 
 | ||
|  | #include <sys/time.h>
 | ||
|  | #include <time.h>
 | ||
|  | 
 | ||
|  | double Kore::System::frequency() { | ||
|  | 	return 1000000.0; | ||
|  | } | ||
|  | 
 | ||
|  | Kore::System::ticks Kore::System::timestamp() { | ||
|  | 	timeval now; | ||
|  | 	gettimeofday(&now, NULL); | ||
|  | 	return static_cast<ticks>(now.tv_sec) * 1000000 + static_cast<ticks>(now.tv_usec); | ||
|  | } | ||
|  | 
 | ||
|  | extern int kore(int argc, char **argv); | ||
|  | 
 | ||
|  | int main(int argc, char **argv) { | ||
|  | 	kore(argc, argv); | ||
|  | } |