rcore_template.c (21085B)
1 /********************************************************************************************** 2 * 3 * rcore_<platform> template - Functions to manage window, graphics device and inputs 4 * 5 * PLATFORM: <PLATFORM> 6 * - TODO: Define the target platform for the core 7 * 8 * LIMITATIONS: 9 * - Limitation 01 10 * - Limitation 02 11 * 12 * POSSIBLE IMPROVEMENTS: 13 * - Improvement 01 14 * - Improvement 02 15 * 16 * ADDITIONAL NOTES: 17 * - TRACELOG() function is located in raylib [utils] module 18 * 19 * CONFIGURATION: 20 * #define RCORE_PLATFORM_CUSTOM_FLAG 21 * Custom flag for rcore on target platform -not used- 22 * 23 * DEPENDENCIES: 24 * - <platform-specific SDK dependency> 25 * - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) 26 * 27 * 28 * LICENSE: zlib/libpng 29 * 30 * Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors 31 * 32 * This software is provided "as-is", without any express or implied warranty. In no event 33 * will the authors be held liable for any damages arising from the use of this software. 34 * 35 * Permission is granted to anyone to use this software for any purpose, including commercial 36 * applications, and to alter it and redistribute it freely, subject to the following restrictions: 37 * 38 * 1. The origin of this software must not be misrepresented; you must not claim that you 39 * wrote the original software. If you use this software in a product, an acknowledgment 40 * in the product documentation would be appreciated but is not required. 41 * 42 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 43 * as being the original software. 44 * 45 * 3. This notice may not be removed or altered from any source distribution. 46 * 47 **********************************************************************************************/ 48 49 // TODO: Include the platform specific libraries 50 51 //---------------------------------------------------------------------------------- 52 // Types and Structures Definition 53 //---------------------------------------------------------------------------------- 54 typedef struct { 55 // TODO: Define the platform specific variables required 56 57 // Display data 58 EGLDisplay device; // Native display device (physical screen connection) 59 EGLSurface surface; // Surface to draw on, framebuffers (connected to context) 60 EGLContext context; // Graphic context, mode in which drawing can be done 61 EGLConfig config; // Graphic config 62 } PlatformData; 63 64 //---------------------------------------------------------------------------------- 65 // Global Variables Definition 66 //---------------------------------------------------------------------------------- 67 extern CoreData CORE; // Global CORE state context 68 69 static PlatformData platform = { 0 }; // Platform specific data 70 71 //---------------------------------------------------------------------------------- 72 // Module Internal Functions Declaration 73 //---------------------------------------------------------------------------------- 74 int InitPlatform(void); // Initialize platform (graphics, inputs and more) 75 bool InitGraphicsDevice(void); // Initialize graphics device 76 77 //---------------------------------------------------------------------------------- 78 // Module Functions Declaration 79 //---------------------------------------------------------------------------------- 80 // NOTE: Functions declaration is provided by raylib.h 81 82 //---------------------------------------------------------------------------------- 83 // Module Functions Definition: Window and Graphics Device 84 //---------------------------------------------------------------------------------- 85 86 // Check if application should close 87 bool WindowShouldClose(void) 88 { 89 if (CORE.Window.ready) return CORE.Window.shouldClose; 90 else return true; 91 } 92 93 // Toggle fullscreen mode 94 void ToggleFullscreen(void) 95 { 96 TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform"); 97 } 98 99 // Toggle borderless windowed mode 100 void ToggleBorderlessWindowed(void) 101 { 102 TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform"); 103 } 104 105 // Set window state: maximized, if resizable 106 void MaximizeWindow(void) 107 { 108 TRACELOG(LOG_WARNING, "MaximizeWindow() not available on target platform"); 109 } 110 111 // Set window state: minimized 112 void MinimizeWindow(void) 113 { 114 TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform"); 115 } 116 117 // Set window state: not minimized/maximized 118 void RestoreWindow(void) 119 { 120 TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform"); 121 } 122 123 // Set window configuration state using flags 124 void SetWindowState(unsigned int flags) 125 { 126 TRACELOG(LOG_WARNING, "SetWindowState() not available on target platform"); 127 } 128 129 // Clear window configuration state flags 130 void ClearWindowState(unsigned int flags) 131 { 132 TRACELOG(LOG_WARNING, "ClearWindowState() not available on target platform"); 133 } 134 135 // Set icon for window 136 void SetWindowIcon(Image image) 137 { 138 TRACELOG(LOG_WARNING, "SetWindowIcon() not available on target platform"); 139 } 140 141 // Set icon for window 142 void SetWindowIcons(Image *images, int count) 143 { 144 TRACELOG(LOG_WARNING, "SetWindowIcons() not available on target platform"); 145 } 146 147 // Set title for window 148 void SetWindowTitle(const char *title) 149 { 150 CORE.Window.title = title; 151 } 152 153 // Set window position on screen (windowed mode) 154 void SetWindowPosition(int x, int y) 155 { 156 TRACELOG(LOG_WARNING, "SetWindowPosition() not available on target platform"); 157 } 158 159 // Set monitor for the current window 160 void SetWindowMonitor(int monitor) 161 { 162 TRACELOG(LOG_WARNING, "SetWindowMonitor() not available on target platform"); 163 } 164 165 // Set window minimum dimensions (FLAG_WINDOW_RESIZABLE) 166 void SetWindowMinSize(int width, int height) 167 { 168 CORE.Window.screenMin.width = width; 169 CORE.Window.screenMin.height = height; 170 } 171 172 // Set window maximum dimensions (FLAG_WINDOW_RESIZABLE) 173 void SetWindowMaxSize(int width, int height) 174 { 175 CORE.Window.screenMax.width = width; 176 CORE.Window.screenMax.height = height; 177 } 178 179 // Set window dimensions 180 void SetWindowSize(int width, int height) 181 { 182 TRACELOG(LOG_WARNING, "SetWindowSize() not available on target platform"); 183 } 184 185 // Set window opacity, value opacity is between 0.0 and 1.0 186 void SetWindowOpacity(float opacity) 187 { 188 TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform"); 189 } 190 191 // Set window focused 192 void SetWindowFocused(void) 193 { 194 TRACELOG(LOG_WARNING, "SetWindowFocused() not available on target platform"); 195 } 196 197 // Get native window handle 198 void *GetWindowHandle(void) 199 { 200 TRACELOG(LOG_WARNING, "GetWindowHandle() not implemented on target platform"); 201 return NULL; 202 } 203 204 // Get number of monitors 205 int GetMonitorCount(void) 206 { 207 TRACELOG(LOG_WARNING, "GetMonitorCount() not implemented on target platform"); 208 return 1; 209 } 210 211 // Get number of monitors 212 int GetCurrentMonitor(void) 213 { 214 TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform"); 215 return 0; 216 } 217 218 // Get selected monitor position 219 Vector2 GetMonitorPosition(int monitor) 220 { 221 TRACELOG(LOG_WARNING, "GetMonitorPosition() not implemented on target platform"); 222 return (Vector2){ 0, 0 }; 223 } 224 225 // Get selected monitor width (currently used by monitor) 226 int GetMonitorWidth(int monitor) 227 { 228 TRACELOG(LOG_WARNING, "GetMonitorWidth() not implemented on target platform"); 229 return 0; 230 } 231 232 // Get selected monitor height (currently used by monitor) 233 int GetMonitorHeight(int monitor) 234 { 235 TRACELOG(LOG_WARNING, "GetMonitorHeight() not implemented on target platform"); 236 return 0; 237 } 238 239 // Get selected monitor physical width in millimetres 240 int GetMonitorPhysicalWidth(int monitor) 241 { 242 TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() not implemented on target platform"); 243 return 0; 244 } 245 246 // Get selected monitor physical height in millimetres 247 int GetMonitorPhysicalHeight(int monitor) 248 { 249 TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() not implemented on target platform"); 250 return 0; 251 } 252 253 // Get selected monitor refresh rate 254 int GetMonitorRefreshRate(int monitor) 255 { 256 TRACELOG(LOG_WARNING, "GetMonitorRefreshRate() not implemented on target platform"); 257 return 0; 258 } 259 260 // Get the human-readable, UTF-8 encoded name of the selected monitor 261 const char *GetMonitorName(int monitor) 262 { 263 TRACELOG(LOG_WARNING, "GetMonitorName() not implemented on target platform"); 264 return ""; 265 } 266 267 // Get window position XY on monitor 268 Vector2 GetWindowPosition(void) 269 { 270 TRACELOG(LOG_WARNING, "GetWindowPosition() not implemented on target platform"); 271 return (Vector2){ 0, 0 }; 272 } 273 274 // Get window scale DPI factor for current monitor 275 Vector2 GetWindowScaleDPI(void) 276 { 277 TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform"); 278 return (Vector2){ 1.0f, 1.0f }; 279 } 280 281 // Set clipboard text content 282 void SetClipboardText(const char *text) 283 { 284 TRACELOG(LOG_WARNING, "SetClipboardText() not implemented on target platform"); 285 } 286 287 // Get clipboard text content 288 // NOTE: returned string is allocated and freed by GLFW 289 const char *GetClipboardText(void) 290 { 291 TRACELOG(LOG_WARNING, "GetClipboardText() not implemented on target platform"); 292 return NULL; 293 } 294 295 // Show mouse cursor 296 void ShowCursor(void) 297 { 298 CORE.Input.Mouse.cursorHidden = false; 299 } 300 301 // Hides mouse cursor 302 void HideCursor(void) 303 { 304 CORE.Input.Mouse.cursorHidden = true; 305 } 306 307 // Enables cursor (unlock cursor) 308 void EnableCursor(void) 309 { 310 // Set cursor position in the middle 311 SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); 312 313 CORE.Input.Mouse.cursorHidden = false; 314 } 315 316 // Disables cursor (lock cursor) 317 void DisableCursor(void) 318 { 319 // Set cursor position in the middle 320 SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); 321 322 CORE.Input.Mouse.cursorHidden = true; 323 } 324 325 // Swap back buffer with front buffer (screen drawing) 326 void SwapScreenBuffer(void) 327 { 328 eglSwapBuffers(platform.device, platform.surface); 329 } 330 331 //---------------------------------------------------------------------------------- 332 // Module Functions Definition: Misc 333 //---------------------------------------------------------------------------------- 334 335 // Get elapsed time measure in seconds since InitTimer() 336 double GetTime(void) 337 { 338 double time = 0.0; 339 struct timespec ts = { 0 }; 340 clock_gettime(CLOCK_MONOTONIC, &ts); 341 unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; 342 343 time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() 344 345 return time; 346 } 347 348 // Open URL with default system browser (if available) 349 // NOTE: This function is only safe to use if you control the URL given. 350 // A user could craft a malicious string performing another action. 351 // Only call this function yourself not with user input or make sure to check the string yourself. 352 // Ref: https://github.com/raysan5/raylib/issues/686 353 void OpenURL(const char *url) 354 { 355 // Security check to (partially) avoid malicious code on target platform 356 if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); 357 else 358 { 359 // TODO: 360 } 361 } 362 363 //---------------------------------------------------------------------------------- 364 // Module Functions Definition: Inputs 365 //---------------------------------------------------------------------------------- 366 367 // Set internal gamepad mappings 368 int SetGamepadMappings(const char *mappings) 369 { 370 TRACELOG(LOG_WARNING, "SetGamepadMappings() not implemented on target platform"); 371 return 0; 372 } 373 374 // Set mouse position XY 375 void SetMousePosition(int x, int y) 376 { 377 CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; 378 CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; 379 } 380 381 // Set mouse cursor 382 void SetMouseCursor(int cursor) 383 { 384 TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); 385 } 386 387 // Get physical key name. 388 const char *GetKeyName(int key) 389 { 390 TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); 391 return ""; 392 } 393 394 // Register all input events 395 void PollInputEvents(void) 396 { 397 #if defined(SUPPORT_GESTURES_SYSTEM) 398 // NOTE: Gestures update must be called every frame to reset gestures correctly 399 // because ProcessGestureEvent() is just called on an event, not every frame 400 UpdateGestures(); 401 #endif 402 403 // Reset keys/chars pressed registered 404 CORE.Input.Keyboard.keyPressedQueueCount = 0; 405 CORE.Input.Keyboard.charPressedQueueCount = 0; 406 407 // Reset key repeats 408 for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; 409 410 // Reset last gamepad button/axis registered state 411 CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN 412 //CORE.Input.Gamepad.axisCount = 0; 413 414 // Register previous touch states 415 for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; 416 417 // Reset touch positions 418 // TODO: It resets on target platform the mouse position and not filled again until a move-event, 419 // so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed! 420 //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; 421 422 // Register previous keys states 423 // NOTE: Android supports up to 260 keys 424 for (int i = 0; i < 260; i++) 425 { 426 CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; 427 CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; 428 } 429 430 // TODO: Poll input events for current platform 431 } 432 433 //---------------------------------------------------------------------------------- 434 // Module Internal Functions Definition 435 //---------------------------------------------------------------------------------- 436 437 // Initialize platform: graphics, inputs and more 438 int InitPlatform(void) 439 { 440 // TODO: Initialize graphic device: display/window 441 // It usually requires setting up the platform display system configuration 442 // and connexion with the GPU through some system graphic API 443 // raylib uses OpenGL so, platform should create that kind of connection 444 // Below example illustrates that process using EGL library 445 //---------------------------------------------------------------------------- 446 CORE.Window.fullscreen = true; 447 CORE.Window.flags |= FLAG_FULLSCREEN_MODE; 448 449 EGLint samples = 0; 450 EGLint sampleBuffer = 0; 451 if (CORE.Window.flags & FLAG_MSAA_4X_HINT) 452 { 453 samples = 4; 454 sampleBuffer = 1; 455 TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4"); 456 } 457 458 const EGLint framebufferAttribs[] = 459 { 460 EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support 461 EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5) 462 EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6) 463 EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5) 464 //EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI) 465 EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!) 466 //EGL_STENCIL_SIZE, 8, // Stencil buffer size 467 EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA 468 EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs) 469 EGL_NONE 470 }; 471 472 const EGLint contextAttribs[] = 473 { 474 EGL_CONTEXT_CLIENT_VERSION, 2, 475 EGL_NONE 476 }; 477 478 EGLint numConfigs = 0; 479 480 // Get an EGL device connection 481 platform.device = eglGetDisplay(EGL_DEFAULT_DISPLAY); 482 if (platform.device == EGL_NO_DISPLAY) 483 { 484 TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); 485 return false; 486 } 487 488 // Initialize the EGL device connection 489 if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE) 490 { 491 // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred. 492 TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); 493 return false; 494 } 495 496 // Get an appropriate EGL framebuffer configuration 497 eglChooseConfig(platform.device, framebufferAttribs, &platform.config, 1, &numConfigs); 498 499 // Set rendering API 500 eglBindAPI(EGL_OPENGL_ES_API); 501 502 // Create an EGL rendering context 503 platform.context = eglCreateContext(platform.device, platform.config, EGL_NO_CONTEXT, contextAttribs); 504 if (platform.context == EGL_NO_CONTEXT) 505 { 506 TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context"); 507 return -1; 508 } 509 510 // Create an EGL window surface 511 EGLint displayFormat = 0; 512 513 // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry() 514 // As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID 515 eglGetConfigAttrib(platform.device, platform.config, EGL_NATIVE_VISUAL_ID, &displayFormat); 516 517 // Android specific call 518 ANativeWindow_setBuffersGeometry(platform.app->window, 0, 0, displayFormat); // Force use of native display size 519 520 platform.surface = eglCreateWindowSurface(platform.device, platform.config, platform.app->window, NULL); 521 522 // There must be at least one frame displayed before the buffers are swapped 523 eglSwapInterval(platform.device, 1); 524 525 EGLBoolean result = eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context); 526 527 // Check surface and context activation 528 if (result != EGL_FALSE) 529 { 530 CORE.Window.ready = true; 531 532 CORE.Window.render.width = CORE.Window.screen.width; 533 CORE.Window.render.height = CORE.Window.screen.height; 534 CORE.Window.currentFbo.width = CORE.Window.render.width; 535 CORE.Window.currentFbo.height = CORE.Window.render.height; 536 537 TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); 538 TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); 539 TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); 540 TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); 541 TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); 542 } 543 else 544 { 545 TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device"); 546 return -1; 547 } 548 //---------------------------------------------------------------------------- 549 550 // If everything work as expected, we can continue 551 CORE.Window.render.width = CORE.Window.screen.width; 552 CORE.Window.render.height = CORE.Window.screen.height; 553 CORE.Window.currentFbo.width = CORE.Window.render.width; 554 CORE.Window.currentFbo.height = CORE.Window.render.height; 555 556 TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); 557 TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); 558 TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); 559 TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); 560 TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); 561 562 // TODO: Load OpenGL extensions 563 // NOTE: GL procedures address loader is required to load extensions 564 //---------------------------------------------------------------------------- 565 rlLoadExtensions(eglGetProcAddress); 566 //---------------------------------------------------------------------------- 567 568 // TODO: Initialize input events system 569 // It could imply keyboard, mouse, gamepad, touch... 570 // Depending on the platform libraries/SDK it could use a callback mechanism 571 // For system events and inputs evens polling on a per-frame basis, use PollInputEvents() 572 //---------------------------------------------------------------------------- 573 // ... 574 //---------------------------------------------------------------------------- 575 576 // TODO: Initialize timing system 577 //---------------------------------------------------------------------------- 578 InitTimer(); 579 //---------------------------------------------------------------------------- 580 581 // TODO: Initialize storage system 582 //---------------------------------------------------------------------------- 583 CORE.Storage.basePath = GetWorkingDirectory(); 584 //---------------------------------------------------------------------------- 585 586 TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully"); 587 588 return 0; 589 } 590 591 // Close platform 592 void ClosePlatform(void) 593 { 594 // TODO: De-initialize graphics, inputs and more 595 } 596 597 // EOF