| @ -0,0 +1,789 @@ | |||
| /********************************************************************************************** | |||
| * | |||
| * rcore_<platform> - Functions to manage window, graphics device and inputs | |||
| * | |||
| * PLATFORM: <PLATFORM> | |||
| * - TODO: Define the target platform for the core | |||
| * | |||
| * LIMITATIONS: | |||
| * - Limitation 01 | |||
| * - Limitation 02 | |||
| * | |||
| * POSSIBLE IMPROVEMENTS: | |||
| * - Improvement 01 | |||
| * - Improvement 02 | |||
| * | |||
| * ADDITIONAL NOTES: | |||
| * - TRACELOG() function is located in raylib [utils] module | |||
| * | |||
| * CONFIGURATION: | |||
| * #define RCORE_CUSTOM_FLAG | |||
| * Custom flag for rcore on PLATFORM_<platform> -not used- | |||
| * | |||
| * DEPENDENCIES: | |||
| * - Dependency 01 | |||
| * - Dependency 02 | |||
| * | |||
| * | |||
| * LICENSE: zlib/libpng | |||
| * | |||
| * Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors | |||
| * | |||
| * This software is provided "as-is", without any express or implied warranty. In no event | |||
| * will the authors be held liable for any damages arising from the use of this software. | |||
| * | |||
| * Permission is granted to anyone to use this software for any purpose, including commercial | |||
| * applications, and to alter it and redistribute it freely, subject to the following restrictions: | |||
| * | |||
| * 1. The origin of this software must not be misrepresented; you must not claim that you | |||
| * wrote the original software. If you use this software in a product, an acknowledgment | |||
| * in the product documentation would be appreciated but is not required. | |||
| * | |||
| * 2. Altered source versions must be plainly marked as such, and must not be misrepresented | |||
| * as being the original software. | |||
| * | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| * | |||
| **********************************************************************************************/ | |||
| #include "rcore.h" | |||
| // TODO: Include the platform specific libraries | |||
| //---------------------------------------------------------------------------------- | |||
| // Types and Structures Definition | |||
| //---------------------------------------------------------------------------------- | |||
| typedef struct { | |||
| // TODO: Define the platform specific variables required | |||
| // Display data | |||
| EGLDisplay device; // Native display device (physical screen connection) | |||
| EGLSurface surface; // Surface to draw on, framebuffers (connected to context) | |||
| EGLContext context; // Graphic context, mode in which drawing can be done | |||
| EGLConfig config; // Graphic config | |||
| } PlatformData; | |||
| //---------------------------------------------------------------------------------- | |||
| // Global Variables Definition | |||
| //---------------------------------------------------------------------------------- | |||
| extern CoreData CORE; // Global CORE state context | |||
| static PlatformData platform = { 0 }; // Platform specific data | |||
| //---------------------------------------------------------------------------------- | |||
| // Module Internal Functions Declaration | |||
| //---------------------------------------------------------------------------------- | |||
| static bool InitGraphicsDevice(int width, int height); // Initialize graphics device | |||
| //---------------------------------------------------------------------------------- | |||
| // Module Functions Declaration | |||
| //---------------------------------------------------------------------------------- | |||
| // NOTE: Functions declaration is provided by raylib.h | |||
| //---------------------------------------------------------------------------------- | |||
| // Module Functions Definition: Window and Graphics Device | |||
| //---------------------------------------------------------------------------------- | |||
| // Initialize window and OpenGL context | |||
| // NOTE: data parameter could be used to pass any kind of required data to the initialization | |||
| void InitWindow(int width, int height, const char *title) | |||
| { | |||
| TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); | |||
| TRACELOG(LOG_INFO, "Supported raylib modules:"); | |||
| TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)"); | |||
| TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)"); | |||
| #if defined(SUPPORT_MODULE_RSHAPES) | |||
| TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)"); | |||
| #else | |||
| TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)"); | |||
| #endif | |||
| #if defined(SUPPORT_MODULE_RTEXTURES) | |||
| TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)"); | |||
| #else | |||
| TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)"); | |||
| #endif | |||
| #if defined(SUPPORT_MODULE_RTEXT) | |||
| TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)"); | |||
| #else | |||
| TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)"); | |||
| #endif | |||
| #if defined(SUPPORT_MODULE_RMODELS) | |||
| TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)"); | |||
| #else | |||
| TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)"); | |||
| #endif | |||
| #if defined(SUPPORT_MODULE_RAUDIO) | |||
| TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)"); | |||
| #else | |||
| TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)"); | |||
| #endif | |||
| // NOTE: Keep internal pointer to input title string (no copy) | |||
| if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; | |||
| // Initialize global input state | |||
| memset(&CORE.Input, 0, sizeof(CORE.Input)); | |||
| CORE.Input.Keyboard.exitKey = KEY_ESCAPE; | |||
| 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; | |||
| CORE.Window.screen.width = width; | |||
| CORE.Window.screen.height = height; | |||
| CORE.Window.currentFbo.width = width; | |||
| CORE.Window.currentFbo.height = height; | |||
| // TODO: Initialize window/display system | |||
| // TODO: Initialize input events system | |||
| // TODO: Initialize assets manager | |||
| // TODO: Initialize base path for storage | |||
| //CORE.Storage.basePath = platform.app->activity->internalDataPath; | |||
| TRACELOG(LOG_INFO, "PLATFORM: Application initialized successfully"); | |||
| } | |||
| // Close window and unload OpenGL context | |||
| void CloseWindow(void) | |||
| { | |||
| #if defined(SUPPORT_GIF_RECORDING) | |||
| if (gifRecording) | |||
| { | |||
| MsfGifResult result = msf_gif_end(&gifState); | |||
| msf_gif_free(result); | |||
| gifRecording = false; | |||
| } | |||
| #endif | |||
| #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) | |||
| UnloadFontDefault(); // WARNING: Module required: rtext | |||
| #endif | |||
| rlglClose(); // De-init rlgl | |||
| #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) | |||
| timeEndPeriod(1); // Restore time period | |||
| #endif | |||
| // TODO: Close surface, context and display | |||
| #if defined(SUPPORT_EVENTS_AUTOMATION) | |||
| RL_FREE(events); | |||
| #endif | |||
| CORE.Window.ready = false; | |||
| TRACELOG(LOG_INFO, "Window closed successfully"); | |||
| } | |||
| // Check if application should close | |||
| bool WindowShouldClose(void) | |||
| { | |||
| if (CORE.Window.ready) return CORE.Window.shouldClose; | |||
| else return true; | |||
| } | |||
| // Check if window is currently hidden | |||
| bool IsWindowHidden(void) | |||
| { | |||
| return false; | |||
| } | |||
| // Check if window has been minimized | |||
| bool IsWindowMinimized(void) | |||
| { | |||
| return false; | |||
| } | |||
| // Check if window has been maximized | |||
| bool IsWindowMaximized(void) | |||
| { | |||
| return false; | |||
| } | |||
| // Check if window has the focus | |||
| bool IsWindowFocused(void) | |||
| { | |||
| return platform.appEnabled; | |||
| } | |||
| // Check if window has been resizedLastFrame | |||
| bool IsWindowResized(void) | |||
| { | |||
| return false; | |||
| } | |||
| // Toggle fullscreen mode | |||
| void ToggleFullscreen(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window state: maximized, if resizable | |||
| void MaximizeWindow(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "MaximizeWindow() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window state: minimized | |||
| void MinimizeWindow(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "MinimizeWindow() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window state: not minimized/maximized | |||
| void RestoreWindow(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "RestoreWindow() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Toggle borderless windowed mode | |||
| void ToggleBorderlessWindowed(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window configuration state using flags | |||
| void SetWindowState(unsigned int flags) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowState() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Clear window configuration state flags | |||
| void ClearWindowState(unsigned int flags) | |||
| { | |||
| TRACELOG(LOG_WARNING, "ClearWindowState() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set icon for window | |||
| void SetWindowIcon(Image image) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowIcon() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set icon for window | |||
| void SetWindowIcons(Image *images, int count) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowIcons() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set title for window | |||
| void SetWindowTitle(const char *title) | |||
| { | |||
| CORE.Window.title = title; | |||
| } | |||
| // Set window position on screen (windowed mode) | |||
| void SetWindowPosition(int x, int y) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowPosition() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set monitor for the current window | |||
| void SetWindowMonitor(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowMonitor() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window minimum dimensions (FLAG_WINDOW_RESIZABLE) | |||
| void SetWindowMinSize(int width, int height) | |||
| { | |||
| CORE.Window.windowMin.width = width; | |||
| CORE.Window.windowMin.height = height; | |||
| } | |||
| // Set window maximum dimensions (FLAG_WINDOW_RESIZABLE) | |||
| void SetWindowMaxSize(int width, int height) | |||
| { | |||
| CORE.Window.windowMax.width = width; | |||
| CORE.Window.windowMax.height = height; | |||
| } | |||
| // Set window dimensions | |||
| void SetWindowSize(int width, int height) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowSize() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window opacity, value opacity is between 0.0 and 1.0 | |||
| void SetWindowOpacity(float opacity) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Set window focused | |||
| void SetWindowFocused(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetWindowFocused() not available on PLATFORM_CUSTOM"); | |||
| } | |||
| // Get native window handle | |||
| void *GetWindowHandle(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetWindowHandle() not implemented on PLATFORM_CUSTOM"); | |||
| return NULL; | |||
| } | |||
| // Get number of monitors | |||
| int GetMonitorCount(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorCount() not implemented on PLATFORM_CUSTOM"); | |||
| return 1; | |||
| } | |||
| // Get number of monitors | |||
| int GetCurrentMonitor(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get selected monitor position | |||
| Vector2 GetMonitorPosition(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorPosition() not implemented on PLATFORM_CUSTOM"); | |||
| return (Vector2){ 0, 0 }; | |||
| } | |||
| // Get selected monitor width (currently used by monitor) | |||
| int GetMonitorWidth(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorWidth() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get selected monitor height (currently used by monitor) | |||
| int GetMonitorHeight(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorHeight() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get selected monitor physical width in millimetres | |||
| int GetMonitorPhysicalWidth(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get selected monitor physical height in millimetres | |||
| int GetMonitorPhysicalHeight(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get selected monitor refresh rate | |||
| int GetMonitorRefreshRate(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorRefreshRate() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get the human-readable, UTF-8 encoded name of the selected monitor | |||
| const char *GetMonitorName(int monitor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMonitorName() not implemented on PLATFORM_CUSTOM"); | |||
| return ""; | |||
| } | |||
| // Get window position XY on monitor | |||
| Vector2 GetWindowPosition(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetWindowPosition() not implemented on PLATFORM_CUSTOM"); | |||
| return (Vector2){ 0, 0 }; | |||
| } | |||
| // Get window scale DPI factor for current monitor | |||
| Vector2 GetWindowScaleDPI(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on PLATFORM_CUSTOM"); | |||
| return (Vector2){ 1.0f, 1.0f }; | |||
| } | |||
| // Set clipboard text content | |||
| void SetClipboardText(const char *text) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetClipboardText() not implemented on PLATFORM_CUSTOM"); | |||
| } | |||
| // Get clipboard text content | |||
| // NOTE: returned string is allocated and freed by GLFW | |||
| const char *GetClipboardText(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetClipboardText() not implemented on PLATFORM_CUSTOM"); | |||
| return NULL; | |||
| } | |||
| // Show mouse cursor | |||
| void ShowCursor(void) | |||
| { | |||
| CORE.Input.Mouse.cursorHidden = false; | |||
| } | |||
| // Hides mouse cursor | |||
| void HideCursor(void) | |||
| { | |||
| CORE.Input.Mouse.cursorHidden = true; | |||
| } | |||
| // Enables cursor (unlock cursor) | |||
| void EnableCursor(void) | |||
| { | |||
| // Set cursor position in the middle | |||
| SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); | |||
| CORE.Input.Mouse.cursorHidden = false; | |||
| } | |||
| // Disables cursor (lock cursor) | |||
| void DisableCursor(void) | |||
| { | |||
| // Set cursor position in the middle | |||
| SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); | |||
| CORE.Input.Mouse.cursorHidden = true; | |||
| } | |||
| // Swap back buffer with front buffer (screen drawing) | |||
| void SwapScreenBuffer(void) | |||
| { | |||
| eglSwapBuffers(platform.device, platform.surface); | |||
| } | |||
| //---------------------------------------------------------------------------------- | |||
| // Module Functions Definition: Misc | |||
| //---------------------------------------------------------------------------------- | |||
| // Get elapsed time measure in seconds since InitTimer() | |||
| double GetTime(void) | |||
| { | |||
| double time = 0.0; | |||
| struct timespec ts = { 0 }; | |||
| clock_gettime(CLOCK_MONOTONIC, &ts); | |||
| unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; | |||
| time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() | |||
| return time; | |||
| } | |||
| // Open URL with default system browser (if available) | |||
| // NOTE: This function is only safe to use if you control the URL given. | |||
| // A user could craft a malicious string performing another action. | |||
| // Only call this function yourself not with user input or make sure to check the string yourself. | |||
| // Ref: https://github.com/raysan5/raylib/issues/686 | |||
| void OpenURL(const char *url) | |||
| { | |||
| // Security check to (partially) avoid malicious code on PLATFORM_CUSTOM | |||
| if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); | |||
| else | |||
| { | |||
| JNIEnv *env = NULL; | |||
| JavaVM *vm = platform.app->activity->vm; | |||
| (*vm)->AttachCurrentThread(vm, &env, NULL); | |||
| jstring urlString = (*env)->NewStringUTF(env, url); | |||
| jclass uriClass = (*env)->FindClass(env, "android/net/Uri"); | |||
| jmethodID uriParse = (*env)->GetStaticMethodID(env, uriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;"); | |||
| jobject uri = (*env)->CallStaticObjectMethod(env, uriClass, uriParse, urlString); | |||
| jclass intentClass = (*env)->FindClass(env, "android/content/Intent"); | |||
| jfieldID actionViewId = (*env)->GetStaticFieldID(env, intentClass, "ACTION_VIEW", "Ljava/lang/String;"); | |||
| jobject actionView = (*env)->GetStaticObjectField(env, intentClass, actionViewId); | |||
| jmethodID newIntent = (*env)->GetMethodID(env, intentClass, "<init>", "(Ljava/lang/String;Landroid/net/Uri;)V"); | |||
| jobject intent = (*env)->AllocObject(env, intentClass); | |||
| (*env)->CallVoidMethod(env, intent, newIntent, actionView, uri); | |||
| jclass activityClass = (*env)->FindClass(env, "android/app/Activity"); | |||
| jmethodID startActivity = (*env)->GetMethodID(env, activityClass, "startActivity", "(Landroid/content/Intent;)V"); | |||
| (*env)->CallVoidMethod(env, platform.app->activity->clazz, startActivity, intent); | |||
| (*vm)->DetachCurrentThread(vm); | |||
| } | |||
| } | |||
| //---------------------------------------------------------------------------------- | |||
| // Module Functions Definition: Inputs | |||
| //---------------------------------------------------------------------------------- | |||
| // Set a custom key to exit program | |||
| void SetExitKey(int key) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetExitKey() not implemented on PLATFORM_CUSTOM"); | |||
| } | |||
| // Get gamepad internal name id | |||
| const char *GetGamepadName(int gamepad) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetGamepadName() not implemented on PLATFORM_CUSTOM"); | |||
| return NULL; | |||
| } | |||
| // Get gamepad axis count | |||
| int GetGamepadAxisCount(int gamepad) | |||
| { | |||
| return CORE.Input.Gamepad.axisCount; | |||
| } | |||
| // Set internal gamepad mappings | |||
| int SetGamepadMappings(const char *mappings) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetGamepadMappings() not implemented on PLATFORM_CUSTOM"); | |||
| return 0; | |||
| } | |||
| // Get mouse position X | |||
| int GetMouseX(void) | |||
| { | |||
| return (int)CORE.Input.Touch.position[0].x; | |||
| } | |||
| // Get mouse position Y | |||
| int GetMouseY(void) | |||
| { | |||
| return (int)CORE.Input.Touch.position[0].y; | |||
| } | |||
| // Get mouse position XY | |||
| Vector2 GetMousePosition(void) | |||
| { | |||
| return GetTouchPosition(0); | |||
| } | |||
| // Set mouse position XY | |||
| void SetMousePosition(int x, int y) | |||
| { | |||
| CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; | |||
| CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; | |||
| } | |||
| // Get mouse wheel movement Y | |||
| float GetMouseWheelMove(void) | |||
| { | |||
| TRACELOG(LOG_WARNING, "GetMouseWheelMove() not implemented on PLATFORM_CUSTOM"); | |||
| return 0.0f; | |||
| } | |||
| // Set mouse cursor | |||
| void SetMouseCursor(int cursor) | |||
| { | |||
| TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on PLATFORM_CUSTOM"); | |||
| } | |||
| // Get touch position X for touch point 0 (relative to screen size) | |||
| int GetTouchX(void) | |||
| { | |||
| return (int)CORE.Input.Touch.position[0].x; | |||
| } | |||
| // Get touch position Y for touch point 0 (relative to screen size) | |||
| int GetTouchY(void) | |||
| { | |||
| return (int)CORE.Input.Touch.position[0].y; | |||
| } | |||
| // Get touch position XY for a touch point index (relative to screen size) | |||
| // TODO: Touch position should be scaled depending on display size and render size | |||
| Vector2 GetTouchPosition(int index) | |||
| { | |||
| Vector2 position = { -1.0f, -1.0f }; | |||
| if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index]; | |||
| else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); | |||
| return position; | |||
| } | |||
| // Register all input events | |||
| void PollInputEvents(void) | |||
| { | |||
| #if defined(SUPPORT_GESTURES_SYSTEM) | |||
| // NOTE: Gestures update must be called every frame to reset gestures correctly | |||
| // because ProcessGestureEvent() is just called on an event, not every frame | |||
| UpdateGestures(); | |||
| #endif | |||
| // Reset keys/chars pressed registered | |||
| CORE.Input.Keyboard.keyPressedQueueCount = 0; | |||
| CORE.Input.Keyboard.charPressedQueueCount = 0; | |||
| // Reset key repeats | |||
| for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; | |||
| // Reset last gamepad button/axis registered state | |||
| CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN | |||
| CORE.Input.Gamepad.axisCount = 0; | |||
| // Register previous touch states | |||
| for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; | |||
| // Reset touch positions | |||
| // TODO: It resets on PLATFORM_CUSTOM the mouse position and not filled again until a move-event, | |||
| // so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed! | |||
| //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; | |||
| // Register previous keys states | |||
| // NOTE: Android supports up to 260 keys | |||
| for (int i = 0; i < 260; i++) | |||
| { | |||
| CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; | |||
| CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; | |||
| } | |||
| // TODO: Poll input events for current plaform | |||
| } | |||
| //---------------------------------------------------------------------------------- | |||
| // 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) | |||
| { | |||
| 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 screen 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; | |||
| EGLint samples = 0; | |||
| EGLint sampleBuffer = 0; | |||
| if (CORE.Window.flags & FLAG_MSAA_4X_HINT) | |||
| { | |||
| samples = 4; | |||
| sampleBuffer = 1; | |||
| TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4"); | |||
| } | |||
| const EGLint framebufferAttribs[] = | |||
| { | |||
| EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support | |||
| EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5) | |||
| EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6) | |||
| EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5) | |||
| //EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI) | |||
| EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!) | |||
| //EGL_STENCIL_SIZE, 8, // Stencil buffer size | |||
| EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA | |||
| EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs) | |||
| EGL_NONE | |||
| }; | |||
| const EGLint contextAttribs[] = | |||
| { | |||
| EGL_CONTEXT_CLIENT_VERSION, 2, | |||
| EGL_NONE | |||
| }; | |||
| EGLint numConfigs = 0; | |||
| // Get an EGL device connection | |||
| platform.device = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |||
| if (platform.device == EGL_NO_DISPLAY) | |||
| { | |||
| TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); | |||
| return false; | |||
| } | |||
| // Initialize the EGL device connection | |||
| if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE) | |||
| { | |||
| // 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; | |||
| } | |||
| // Get an appropriate EGL framebuffer configuration | |||
| eglChooseConfig(platform.device, framebufferAttribs, &platform.config, 1, &numConfigs); | |||
| // Set rendering API | |||
| eglBindAPI(EGL_OPENGL_ES_API); | |||
| // Create an EGL rendering context | |||
| platform.context = eglCreateContext(platform.device, platform.config, EGL_NO_CONTEXT, contextAttribs); | |||
| if (platform.context == EGL_NO_CONTEXT) | |||
| { | |||
| TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context"); | |||
| return false; | |||
| } | |||
| // Create an EGL window surface | |||
| //--------------------------------------------------------------------------------- | |||
| EGLint displayFormat = 0; | |||
| // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry() | |||
| // As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID | |||
| eglGetConfigAttrib(platform.device, platform.config, EGL_NATIVE_VISUAL_ID, &displayFormat); | |||
| // At this point we need to manage render size vs screen size | |||
| // NOTE: This function use and modify global module variables: | |||
| // -> CORE.Window.screen.width/CORE.Window.screen.height | |||
| // -> CORE.Window.render.width/CORE.Window.render.height | |||
| // -> CORE.Window.screenScale | |||
| SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); | |||
| ANativeWindow_setBuffersGeometry(platform.app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat); | |||
| //ANativeWindow_setBuffersGeometry(platform.app->window, 0, 0, displayFormat); // Force use of native display size | |||
| platform.surface = eglCreateWindowSurface(platform.device, platform.config, platform.app->window, NULL); | |||
| // There must be at least one frame displayed before the buffers are swapped | |||
| //eglSwapInterval(platform.device, 1); | |||
| 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; | |||
| } | |||
| else | |||
| { | |||
| CORE.Window.render.width = CORE.Window.screen.width; | |||
| CORE.Window.render.height = CORE.Window.screen.height; | |||
| CORE.Window.currentFbo.width = CORE.Window.render.width; | |||
| CORE.Window.currentFbo.height = CORE.Window.render.height; | |||
| TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); | |||
| TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); | |||
| TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); | |||
| TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); | |||
| TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); | |||
| } | |||
| // Load OpenGL extensions | |||
| // 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); | |||
| // Setup default viewport | |||
| // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height | |||
| SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); | |||
| CORE.Window.ready = true; | |||
| if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); | |||
| return true; | |||
| } | |||
| // EOF | |||