|
@@ -140,21 +140,22 @@ static PlatformData platform = { 0 }; // Platform specific data
|
|
|
//----------------------------------------------------------------------------------
|
|
|
// Module Internal Functions Declaration
|
|
|
//----------------------------------------------------------------------------------
|
|
|
-static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
|
|
+static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
|
|
|
+static void ClosePlatform(void); // Close platform
|
|
|
|
|
|
-static void InitKeyboard(void); // Initialize raw keyboard system
|
|
|
-static void RestoreKeyboard(void); // Restore keyboard system
|
|
|
+static void InitKeyboard(void); // Initialize raw keyboard system
|
|
|
+static void RestoreKeyboard(void); // Restore keyboard system
|
|
|
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
|
|
-static void ProcessKeyboard(void); // Process keyboard events
|
|
|
+static void ProcessKeyboard(void); // Process keyboard events
|
|
|
#endif
|
|
|
|
|
|
-static void InitEvdevInput(void); // Initialize evdev inputs
|
|
|
-static void ConfigureEvdevDevice(char *device); // Identifies a input device and configures it for use if appropriate
|
|
|
-static void PollKeyboardEvents(void); // Process evdev keyboard events
|
|
|
-static void *EventThread(void *arg); // Input device events reading thread
|
|
|
+static void InitEvdevInput(void); // Initialize evdev inputs
|
|
|
+static void ConfigureEvdevDevice(char *device); // Identifies a input device and configures it for use if appropriate
|
|
|
+static void PollKeyboardEvents(void); // Process evdev keyboard events
|
|
|
+static void *EventThread(void *arg); // Input device events reading thread
|
|
|
|
|
|
-static void InitGamepad(void); // Initialize raw gamepad input
|
|
|
-static void *GamepadThread(void *arg); // Mouse reading thread
|
|
|
+static void InitGamepad(void); // Initialize raw gamepad input
|
|
|
+static void *GamepadThread(void *arg); // Mouse reading thread
|
|
|
|
|
|
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
|
|
|
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
|
|
@@ -204,49 +205,31 @@ void InitWindow(int width, int height, const char *title)
|
|
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
|
|
#endif
|
|
|
|
|
|
- // NOTE: Keep internal pointer to input title string (no copy)
|
|
|
+ // Initialize window data
|
|
|
+ CORE.Window.screen.width = width;
|
|
|
+ CORE.Window.screen.height = height;
|
|
|
+ CORE.Window.eventWaiting = false;
|
|
|
+ CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
|
|
|
|
|
// Initialize global input state
|
|
|
- memset(&CORE.Input, 0, sizeof(CORE.Input));
|
|
|
+ memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
|
|
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
|
|
- CORE.Input.Mouse.scale = (Vector2){1.0f, 1.0f};
|
|
|
+ CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
|
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
|
|
- CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
|
|
- CORE.Window.eventWaiting = false;
|
|
|
-
|
|
|
-
|
|
|
- // Platform specific init window
|
|
|
- //--------------------------------------------------------------
|
|
|
- // Initialize graphics device (display device and OpenGL context)
|
|
|
- // NOTE: returns true if window and graphic device has been initialized successfully
|
|
|
- CORE.Window.ready = InitGraphicsDevice(width, height);
|
|
|
-
|
|
|
- // If graphic device is no properly initialized, we end program
|
|
|
- if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
|
|
|
- else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
|
|
|
-
|
|
|
- // Set some default window flags
|
|
|
- CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
|
|
|
- CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // false
|
|
|
- CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
|
|
|
- CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
|
|
|
-
|
|
|
- // Initialize hi-res timer
|
|
|
- InitTimer();
|
|
|
-
|
|
|
- // Initialize base path for storage
|
|
|
- CORE.Storage.basePath = GetWorkingDirectory();
|
|
|
-
|
|
|
- // Initialize raw input system
|
|
|
- InitEvdevInput(); // Evdev inputs initialization
|
|
|
- InitGamepad(); // Gamepad init
|
|
|
- InitKeyboard(); // Keyboard init (stdin)
|
|
|
+ CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
|
|
|
+
|
|
|
+ // Initialize platform
|
|
|
+ //--------------------------------------------------------------
|
|
|
+ InitPlatform();
|
|
|
//--------------------------------------------------------------
|
|
|
+
|
|
|
+ // Initialize rlgl default data (buffers and shaders)
|
|
|
+ // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
|
|
+ rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
|
|
|
|
-
|
|
|
- // Initialize random seed
|
|
|
- SetRandomSeed((unsigned int)time(NULL));
|
|
|
+ // Setup default viewport
|
|
|
+ SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
|
|
|
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
|
// Load default font
|
|
@@ -289,7 +272,10 @@ void InitWindow(int width, int height, const char *title)
|
|
|
events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent));
|
|
|
CORE.Time.frameCounter = 0;
|
|
|
#endif
|
|
|
-
|
|
|
+
|
|
|
+ // Initialize random seed
|
|
|
+ SetRandomSeed((unsigned int)time(NULL));
|
|
|
+
|
|
|
TRACELOG(LOG_INFO, "PLATFORM: DRM: Application initialized successfully");
|
|
|
}
|
|
|
|
|
@@ -315,93 +301,9 @@ void CloseWindow(void)
|
|
|
timeEndPeriod(1); // Restore time period
|
|
|
#endif
|
|
|
|
|
|
- // Platform specific close window
|
|
|
- //--------------------------------------------------------------
|
|
|
- if (platform.prevFB)
|
|
|
- {
|
|
|
- drmModeRmFB(platform.fd, platform.prevFB);
|
|
|
- platform.prevFB = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.prevBO)
|
|
|
- {
|
|
|
- gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
|
|
|
- platform.prevBO = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.gbmSurface)
|
|
|
- {
|
|
|
- gbm_surface_destroy(platform.gbmSurface);
|
|
|
- platform.gbmSurface = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.gbmDevice)
|
|
|
- {
|
|
|
- gbm_device_destroy(platform.gbmDevice);
|
|
|
- platform.gbmDevice = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.crtc)
|
|
|
- {
|
|
|
- if (platform.connector)
|
|
|
- {
|
|
|
- drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
|
|
|
- platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
|
|
|
- drmModeFreeConnector(platform.connector);
|
|
|
- platform.connector = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- drmModeFreeCrtc(platform.crtc);
|
|
|
- platform.crtc = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.fd != -1)
|
|
|
- {
|
|
|
- close(platform.fd);
|
|
|
- platform.fd = -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Close surface, context and display
|
|
|
- if (platform.device != EGL_NO_DISPLAY)
|
|
|
- {
|
|
|
- if (platform.surface != EGL_NO_SURFACE)
|
|
|
- {
|
|
|
- eglDestroySurface(platform.device, platform.surface);
|
|
|
- platform.surface = EGL_NO_SURFACE;
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.context != EGL_NO_CONTEXT)
|
|
|
- {
|
|
|
- eglDestroyContext(platform.device, platform.context);
|
|
|
- platform.context = EGL_NO_CONTEXT;
|
|
|
- }
|
|
|
-
|
|
|
- eglTerminate(platform.device);
|
|
|
- platform.device = EGL_NO_DISPLAY;
|
|
|
- }
|
|
|
-
|
|
|
- // Wait for mouse and gamepad threads to finish before closing
|
|
|
- // NOTE: Those threads should already have finished at this point
|
|
|
- // because they are controlled by CORE.Window.shouldClose variable
|
|
|
-
|
|
|
- CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
|
|
|
-
|
|
|
- // Close the evdev keyboard
|
|
|
- if (platform.keyboardFd != -1)
|
|
|
- {
|
|
|
- close(platform.keyboardFd);
|
|
|
- platform.keyboardFd = -1;
|
|
|
- }
|
|
|
-
|
|
|
- for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
|
|
- {
|
|
|
- if (platform.eventWorker[i].threadId)
|
|
|
- {
|
|
|
- pthread_join(platform.eventWorker[i].threadId, NULL);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
|
|
|
+ // De-initialize platform
|
|
|
+ //--------------------------------------------------------------
|
|
|
+ ClosePlatform();
|
|
|
//--------------------------------------------------------------
|
|
|
|
|
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
|
@@ -808,28 +710,9 @@ void PollInputEvents(void)
|
|
|
// Module Internal Functions Definition
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
|
|
-// Initialize display device and framebuffer
|
|
|
-// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
|
|
-// If width or height are 0, default display size will be used for framebuffer size
|
|
|
-// NOTE: returns false in case graphic device could not be created
|
|
|
-static bool InitGraphicsDevice(int width, int height)
|
|
|
+// Initialize platform: graphics, inputs and more
|
|
|
+static int InitPlatform(void)
|
|
|
{
|
|
|
- CORE.Window.screen.width = width; // User desired width
|
|
|
- CORE.Window.screen.height = height; // User desired height
|
|
|
- CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
|
-
|
|
|
- // Set the window minimum and maximum default values to 0
|
|
|
- CORE.Window.screenMin.width = 0;
|
|
|
- CORE.Window.screenMin.height = 0;
|
|
|
- CORE.Window.screenMax.width = 0;
|
|
|
- CORE.Window.screenMax.height = 0;
|
|
|
-
|
|
|
- // NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
|
|
- // ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
|
|
-
|
|
|
- CORE.Window.fullscreen = true;
|
|
|
- CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
|
|
-
|
|
|
platform.fd = -1;
|
|
|
platform.connector = NULL;
|
|
|
platform.modeIndex = -1;
|
|
@@ -838,6 +721,9 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
platform.gbmSurface = NULL;
|
|
|
platform.prevBO = NULL;
|
|
|
platform.prevFB = 0;
|
|
|
+
|
|
|
+ CORE.Window.fullscreen = true;
|
|
|
+ CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
|
|
|
|
|
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
|
|
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
|
@@ -861,14 +747,14 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (platform.fd == -1)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
drmModeRes *res = drmModeGetResources(platform.fd);
|
|
|
if (!res)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
TRACELOG(LOG_TRACE, "DISPLAY: Connectors found: %i", res->count_connectors);
|
|
@@ -897,7 +783,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: No suitable DRM connector found");
|
|
|
drmModeFreeResources(res);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
|
|
@@ -905,7 +791,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
|
|
|
drmModeFreeResources(res);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
platform.crtc = drmModeGetCrtc(platform.fd, enc->crtc_id);
|
|
@@ -914,7 +800,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
|
|
|
drmModeFreeEncoder(enc);
|
|
|
drmModeFreeResources(res);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
// If InitWindow should use the current mode find it in the connector's mode list
|
|
@@ -929,7 +815,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
|
|
|
drmModeFreeEncoder(enc);
|
|
|
drmModeFreeResources(res);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
CORE.Window.screen.width = CORE.Window.display.width;
|
|
@@ -957,7 +843,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable DRM connector mode");
|
|
|
drmModeFreeEncoder(enc);
|
|
|
drmModeFreeResources(res);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay;
|
|
@@ -982,7 +868,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (!platform.gbmDevice)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM device");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
platform.gbmSurface = gbm_surface_create(platform.gbmDevice, platform.connector->modes[platform.modeIndex].hdisplay,
|
|
@@ -990,7 +876,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (!platform.gbmSurface)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM surface");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
EGLint samples = 0;
|
|
@@ -1030,7 +916,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (platform.device == EGL_NO_DISPLAY)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
// Initialize the EGL device connection
|
|
@@ -1038,13 +924,13 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
{
|
|
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
|
@@ -1053,7 +939,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (!configs)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
EGLint matchingNumConfigs = 0;
|
|
@@ -1061,7 +947,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to choose EGL config: 0x%x", eglGetError());
|
|
|
free(configs);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
TRACELOG(LOG_TRACE, "DISPLAY: EGL matching configs available: %d", matchingNumConfigs);
|
|
@@ -1091,7 +977,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (!found)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable EGL config");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
// Set rendering API
|
|
@@ -1102,7 +988,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (platform.context == EGL_NO_CONTEXT)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
// Create an EGL window surface
|
|
@@ -1111,7 +997,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (EGL_NO_SURFACE == platform.surface)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL window surface: 0x%04x", eglGetError());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
// At this point we need to manage render size vs screen size
|
|
@@ -1127,7 +1013,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
|
|
{
|
|
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -1147,19 +1033,123 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
// NOTE: GL procedures address loader is required to load extensions
|
|
|
rlLoadExtensions(eglGetProcAddress);
|
|
|
|
|
|
- // Initialize OpenGL context (states and resources)
|
|
|
- // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
|
|
- rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
|
+ if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
|
|
+
|
|
|
+ // If graphic device is no properly initialized, we end program
|
|
|
+ if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
|
|
|
+ else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
|
|
|
|
|
|
- // Setup default viewport
|
|
|
- // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
|
|
- SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
|
+ // Set some default window flags
|
|
|
+ CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
|
|
|
+ CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // false
|
|
|
+ CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
|
|
|
+ CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
|
|
|
|
|
|
- if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
|
|
+ // Initialize hi-res timer
|
|
|
+ InitTimer();
|
|
|
|
|
|
- return true;
|
|
|
+ // Initialize base path for storage
|
|
|
+ CORE.Storage.basePath = GetWorkingDirectory();
|
|
|
+
|
|
|
+ // Initialize raw input system
|
|
|
+ InitEvdevInput(); // Evdev inputs initialization
|
|
|
+ InitGamepad(); // Gamepad init
|
|
|
+ InitKeyboard(); // Keyboard init (stdin)
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
+// Close platform
|
|
|
+static void ClosePlatform(void)
|
|
|
+{
|
|
|
+ if (platform.prevFB)
|
|
|
+ {
|
|
|
+ drmModeRmFB(platform.fd, platform.prevFB);
|
|
|
+ platform.prevFB = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.prevBO)
|
|
|
+ {
|
|
|
+ gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
|
|
|
+ platform.prevBO = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.gbmSurface)
|
|
|
+ {
|
|
|
+ gbm_surface_destroy(platform.gbmSurface);
|
|
|
+ platform.gbmSurface = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.gbmDevice)
|
|
|
+ {
|
|
|
+ gbm_device_destroy(platform.gbmDevice);
|
|
|
+ platform.gbmDevice = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.crtc)
|
|
|
+ {
|
|
|
+ if (platform.connector)
|
|
|
+ {
|
|
|
+ drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
|
|
|
+ platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
|
|
|
+ drmModeFreeConnector(platform.connector);
|
|
|
+ platform.connector = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ drmModeFreeCrtc(platform.crtc);
|
|
|
+ platform.crtc = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.fd != -1)
|
|
|
+ {
|
|
|
+ close(platform.fd);
|
|
|
+ platform.fd = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close surface, context and display
|
|
|
+ if (platform.device != EGL_NO_DISPLAY)
|
|
|
+ {
|
|
|
+ if (platform.surface != EGL_NO_SURFACE)
|
|
|
+ {
|
|
|
+ eglDestroySurface(platform.device, platform.surface);
|
|
|
+ platform.surface = EGL_NO_SURFACE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.context != EGL_NO_CONTEXT)
|
|
|
+ {
|
|
|
+ eglDestroyContext(platform.device, platform.context);
|
|
|
+ platform.context = EGL_NO_CONTEXT;
|
|
|
+ }
|
|
|
+
|
|
|
+ eglTerminate(platform.device);
|
|
|
+ platform.device = EGL_NO_DISPLAY;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for mouse and gamepad threads to finish before closing
|
|
|
+ // NOTE: Those threads should already have finished at this point
|
|
|
+ // because they are controlled by CORE.Window.shouldClose variable
|
|
|
+
|
|
|
+ CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
|
|
|
+
|
|
|
+ // Close the evdev keyboard
|
|
|
+ if (platform.keyboardFd != -1)
|
|
|
+ {
|
|
|
+ close(platform.keyboardFd);
|
|
|
+ platform.keyboardFd = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
|
|
+ {
|
|
|
+ if (platform.eventWorker[i].threadId)
|
|
|
+ {
|
|
|
+ pthread_join(platform.eventWorker[i].threadId, NULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
// Initialize Keyboard system (using standard input)
|
|
|
static void InitKeyboard(void)
|
|
|
{
|