WARNING: REDESIGN: Move platform specific data to platform submodules #3313
REVIEWED: Defines, macros, types and tweaks
This commit is contained in:
parent
bbbaae5562
commit
d445fdaa19
7 changed files with 519 additions and 520 deletions
70
src/rcore.c
70
src/rcore.c
|
@ -1,33 +1,18 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* rcore - Basic functions to manage windows, OpenGL context and input on multiple platforms
|
* rcore - Window/display management, Graphic device/context management and input management
|
||||||
*
|
*
|
||||||
* PLATFORMS SUPPORTED:
|
* PLATFORMS SUPPORTED:
|
||||||
* - PLATFORM_DESKTOP: Windows (Win32, Win64)
|
* - PLATFORM_DESKTOP: Windows (Win32, Win64)
|
||||||
* - PLATFORM_DESKTOP: Linux (X11 desktop mode)
|
* - PLATFORM_DESKTOP: Linux (X11 desktop mode)
|
||||||
* - PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
|
* - PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
|
||||||
* - PLATFORM_DESKTOP: OSX/macOS
|
* - PLATFORM_DESKTOP: OSX/macOS
|
||||||
|
* - PLATFORM_WEB: HTML5 (WebAssembly)
|
||||||
|
* - PLATFORM_DRM: Raspberry Pi 0-5
|
||||||
|
* - PLATFORM_DRM: Linux native mode (KMS driver)
|
||||||
* - PLATFORM_ANDROID: Android (ARM, ARM64)
|
* - PLATFORM_ANDROID: Android (ARM, ARM64)
|
||||||
* - PLATFORM_DRM: Linux native mode, including Raspberry Pi 4 with V3D fkms driver
|
|
||||||
* - PLATFORM_WEB: HTML5 with WebAssembly
|
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define PLATFORM_DESKTOP
|
|
||||||
* Windowing and input system configured for desktop platforms:
|
|
||||||
* Windows, Linux, OSX, FreeBSD, OpenBSD, NetBSD, DragonFly
|
|
||||||
*
|
|
||||||
* #define PLATFORM_ANDROID
|
|
||||||
* Windowing and input system configured for Android device, app activity managed internally in this module.
|
|
||||||
* NOTE: OpenGL ES 2.0 is required and graphic device is managed by EGL
|
|
||||||
*
|
|
||||||
* #define PLATFORM_DRM
|
|
||||||
* Windowing and input system configured for DRM native mode (RPI4 and other devices)
|
|
||||||
* graphic device is managed by EGL and inputs are processed is raw mode, reading from /dev/input/
|
|
||||||
*
|
|
||||||
* #define PLATFORM_WEB
|
|
||||||
* Windowing and input system configured for HTML5 (run on browser), code converted from C to asm.js
|
|
||||||
* using emscripten compiler. OpenGL ES 2.0 required for direct translation to WebGL equivalent code.
|
|
||||||
*
|
|
||||||
* #define SUPPORT_DEFAULT_FONT (default)
|
* #define SUPPORT_DEFAULT_FONT (default)
|
||||||
* Default font is loaded on window initialization to be available for the user to render simple text.
|
* Default font is loaded on window initialization to be available for the user to render simple text.
|
||||||
* NOTE: If enabled, uses external module functions to load default raylib font (module: text)
|
* NOTE: If enabled, uses external module functions to load default raylib font (module: text)
|
||||||
|
@ -42,11 +27,6 @@
|
||||||
* #define SUPPORT_MOUSE_GESTURES
|
* #define SUPPORT_MOUSE_GESTURES
|
||||||
* Mouse gestures are directly mapped like touches and processed by gestures system.
|
* Mouse gestures are directly mapped like touches and processed by gestures system.
|
||||||
*
|
*
|
||||||
* #define SUPPORT_SSH_KEYBOARD_RPI (Raspberry Pi only)
|
|
||||||
* Reconfigure standard input to receive key inputs, works with SSH connection.
|
|
||||||
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other
|
|
||||||
* running processes orblocking the device if not restored properly. Use with care.
|
|
||||||
*
|
|
||||||
* #define SUPPORT_BUSY_WAIT_LOOP
|
* #define SUPPORT_BUSY_WAIT_LOOP
|
||||||
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
||||||
*
|
*
|
||||||
|
@ -68,7 +48,6 @@
|
||||||
* Support automatic generated events, loading and recording of those events when required
|
* Support automatic generated events, loading and recording of those events when required
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX, FreeBSD...)
|
|
||||||
* raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion)
|
* raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion)
|
||||||
* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person)
|
* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person)
|
||||||
* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs)
|
* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs)
|
||||||
|
@ -76,7 +55,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -102,7 +81,7 @@
|
||||||
#include "config.h" // Defines module configuration flags
|
#include "config.h" // Defines module configuration flags
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rcore.h"
|
#include "rcore.h" // Defines types and globals
|
||||||
|
|
||||||
#define RLGL_IMPLEMENTATION
|
#define RLGL_IMPLEMENTATION
|
||||||
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||||
|
@ -142,21 +121,19 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Platform specific defines to handle GetApplicationDirectory()
|
// Platform specific defines to handle GetApplicationDirectory()
|
||||||
#if defined (PLATFORM_DESKTOP)
|
#if defined(_WIN32)
|
||||||
#if defined(_WIN32)
|
#ifndef MAX_PATH
|
||||||
#ifndef MAX_PATH
|
#define MAX_PATH 1025
|
||||||
#define MAX_PATH 1025
|
#endif
|
||||||
#endif
|
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize);
|
||||||
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize);
|
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize);
|
||||||
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize);
|
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default);
|
||||||
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default);
|
#elif defined(__linux__)
|
||||||
#elif defined(__linux__)
|
#include <unistd.h>
|
||||||
#include <unistd.h>
|
#elif defined(__APPLE__)
|
||||||
#elif defined(__APPLE__)
|
#include <sys/syslimits.h>
|
||||||
#include <sys/syslimits.h>
|
#include <mach-o/dyld.h>
|
||||||
#include <mach-o/dyld.h>
|
#endif // OSs
|
||||||
#endif // OSs
|
|
||||||
#endif // PLATFORM_DESKTOP
|
|
||||||
|
|
||||||
#define _CRT_INTERNAL_NONSTDC_NAMES 1
|
#define _CRT_INTERNAL_NONSTDC_NAMES 1
|
||||||
#include <sys/stat.h> // Required for: stat(), S_ISREG [Used in GetFileModTime(), IsFilePath()]
|
#include <sys/stat.h> // Required for: stat(), S_ISREG [Used in GetFileModTime(), IsFilePath()]
|
||||||
|
@ -165,7 +142,7 @@
|
||||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) && defined(_WIN32) && (defined(_MSC_VER) || defined(__TINYC__))
|
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__TINYC__))
|
||||||
#define DIRENT_MALLOC RL_MALLOC
|
#define DIRENT_MALLOC RL_MALLOC
|
||||||
#define DIRENT_FREE RL_FREE
|
#define DIRENT_FREE RL_FREE
|
||||||
|
|
||||||
|
@ -333,7 +310,8 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
|
||||||
#elif defined(PLATFORM_ANDROID)
|
#elif defined(PLATFORM_ANDROID)
|
||||||
#include "rcore_android.c"
|
#include "rcore_android.c"
|
||||||
#else
|
#else
|
||||||
// Software rendering backend, user needs to provide buffer ;)
|
// TODO: Include your custom platform backend!
|
||||||
|
// i.e software rendering backend or console backend!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -1897,7 +1875,7 @@ bool IsKeyPressed(int key)
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a key has been pressed again (only PLATFORM_DESKTOP)
|
// Check if a key has been pressed again
|
||||||
bool IsKeyPressedRepeat(int key)
|
bool IsKeyPressedRepeat(int key)
|
||||||
{
|
{
|
||||||
bool repeat = false;
|
bool repeat = false;
|
||||||
|
@ -2291,7 +2269,7 @@ void InitTimer(void)
|
||||||
timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms)
|
timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
||||||
struct timespec now = { 0 };
|
struct timespec now = { 0 };
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
||||||
|
|
149
src/rcore.h
149
src/rcore.h
|
@ -35,64 +35,6 @@
|
||||||
#ifndef RCORE_H
|
#ifndef RCORE_H
|
||||||
#define RCORE_H
|
#define RCORE_H
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: srand(), rand(), atexit()
|
|
||||||
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
|
|
||||||
#include <string.h> // Required for: strrchr(), strcmp(), strlen(), memset()
|
|
||||||
#include <time.h> // Required for: time() [Used in InitTimer()]
|
|
||||||
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
|
|
||||||
|
|
||||||
#include "utils.h" // Required for: TRACELOG() macros
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3
|
|
||||||
// NOTE: Already provided by rlgl implementation (on glad.h)
|
|
||||||
#include "GLFW/glfw3.h" // GLFW3 library: Windows, OpenGL context and Input management
|
|
||||||
// NOTE: GLFW3 already includes gl.h (OpenGL) headers
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
|
||||||
#include <EGL/egl.h> // Native platform windowing system interface
|
|
||||||
//#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
|
|
||||||
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
|
||||||
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
|
||||||
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
|
||||||
#include <pthread.h> // POSIX threads management (inputs reading)
|
|
||||||
#include <dirent.h> // POSIX directory browsing
|
|
||||||
|
|
||||||
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
|
||||||
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
|
||||||
#include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...)
|
|
||||||
#include <linux/joystick.h> // Linux: Joystick support library
|
|
||||||
|
|
||||||
#include <gbm.h> // Generic Buffer Management (native platform for EGL on DRM)
|
|
||||||
#include <xf86drm.h> // Direct Rendering Manager user-level library interface
|
|
||||||
#include <xf86drmMode.h> // Direct Rendering Manager mode setting (KMS) interface
|
|
||||||
|
|
||||||
#include "EGL/egl.h" // Native platform windowing system interface
|
|
||||||
#include "EGL/eglext.h" // EGL extensions
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
pthread_t threadId; // Event reading thread id
|
|
||||||
int fd; // File descriptor to the device it is assigned to
|
|
||||||
int eventNum; // Number of 'event<N>' device
|
|
||||||
Rectangle absRange; // Range of values for absolute pointing devices (touchscreens)
|
|
||||||
int touchSlot; // Hold the touch slot number of the currently being sent multitouch block
|
|
||||||
bool isMouse; // True if device supports relative X Y movements
|
|
||||||
bool isTouch; // True if device supports absolute X Y movements and has BTN_TOUCH
|
|
||||||
bool isMultitouch; // True if device supports multiple absolute movevents and has BTN_TOUCH
|
|
||||||
bool isKeyboard; // True if device has letter keycodes
|
|
||||||
bool isGamepad; // True if device has gamepad buttons
|
|
||||||
} InputEventWorker;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: PROVIDE A HEADER TO BE USED BY ALL THE rcore_* IMPLEMENTATIONS
|
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include "rlgl.h"
|
#include "rlgl.h"
|
||||||
|
@ -100,16 +42,17 @@
|
||||||
#define RAYMATH_IMPLEMENTATION
|
#define RAYMATH_IMPLEMENTATION
|
||||||
#include "raymath.h"
|
#include "raymath.h"
|
||||||
|
|
||||||
|
#include "utils.h" // Required for: TRACELOG() macros
|
||||||
|
|
||||||
|
#include <stdlib.h> // Required for: srand(), rand(), atexit()
|
||||||
|
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
|
||||||
|
#include <string.h> // Required for: strrchr(), strcmp(), strlen(), memset()
|
||||||
|
#include <time.h> // Required for: time() [Used in InitTimer()]
|
||||||
|
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
|
||||||
|
|
||||||
#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...)
|
|
||||||
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX_FILEPATH_CAPACITY
|
#ifndef MAX_FILEPATH_CAPACITY
|
||||||
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
|
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
|
||||||
#endif
|
#endif
|
||||||
|
@ -152,12 +95,6 @@
|
||||||
#define FLAG_TOGGLE(n, f) ((n) ^= (f))
|
#define FLAG_TOGGLE(n, f) ((n) ^= (f))
|
||||||
#define FLAG_CHECK(n, f) ((n) & (f))
|
#define FLAG_CHECK(n, f) ((n) & (f))
|
||||||
|
|
||||||
// TODO: HACK: Added flag if not provided by GLFW when using external library
|
|
||||||
// Latest GLFW release (GLFW 3.3.8) does not implement this flag, it was added for 3.4.0-dev
|
|
||||||
#if !defined(GLFW_MOUSE_PASSTHROUGH)
|
|
||||||
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && (_POSIX_C_SOURCE < 199309L)
|
#if (defined(__linux__) || defined(PLATFORM_WEB)) && (_POSIX_C_SOURCE < 199309L)
|
||||||
#undef _POSIX_C_SOURCE
|
#undef _POSIX_C_SOURCE
|
||||||
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
||||||
|
@ -172,25 +109,6 @@ typedef struct { unsigned int width; unsigned int height; } Size;
|
||||||
// Core global state context data
|
// Core global state context data
|
||||||
typedef struct CoreData {
|
typedef struct CoreData {
|
||||||
struct {
|
struct {
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
GLFWwindow *handle; // GLFW window handle (graphic device)
|
|
||||||
#endif
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
int fd; // File descriptor for /dev/dri/...
|
|
||||||
drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector
|
|
||||||
drmModeCrtc *crtc; // CRT Controller
|
|
||||||
int modeIndex; // Index of the used mode of connector->modes
|
|
||||||
struct gbm_device *gbmDevice; // GBM device
|
|
||||||
struct gbm_surface *gbmSurface; // GBM surface
|
|
||||||
struct gbm_bo *prevBO; // Previous GBM buffer object (during frame swapping)
|
|
||||||
uint32_t prevFB; // Previous GBM framebufer (during frame swapping)
|
|
||||||
#endif // PLATFORM_DRM
|
|
||||||
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
|
|
||||||
#endif
|
|
||||||
const char *title; // Window text title const pointer
|
const char *title; // Window text title const pointer
|
||||||
unsigned int flags; // Configuration flags (bit based), keeps window state
|
unsigned int flags; // Configuration flags (bit based), keeps window state
|
||||||
bool ready; // Check if window has been initialized successfully
|
bool ready; // Check if window has been initialized successfully
|
||||||
|
@ -215,45 +133,27 @@ typedef struct CoreData {
|
||||||
|
|
||||||
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
||||||
unsigned int dropFileCount; // Count dropped files strings
|
unsigned int dropFileCount; // Count dropped files strings
|
||||||
|
|
||||||
} Window;
|
} Window;
|
||||||
#if defined(PLATFORM_ANDROID)
|
|
||||||
struct {
|
|
||||||
bool appEnabled; // Flag to detect if app is active ** = true
|
|
||||||
struct android_app *app; // Android activity
|
|
||||||
struct android_poll_source *source; // Android events polling source
|
|
||||||
bool contextRebindRequired; // Used to know context rebind required
|
|
||||||
} Android;
|
|
||||||
#endif
|
|
||||||
struct {
|
struct {
|
||||||
const char *basePath; // Base path for data storage
|
const char *basePath; // Base path for data storage
|
||||||
|
|
||||||
} Storage;
|
} Storage;
|
||||||
struct {
|
struct {
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>"
|
|
||||||
#endif
|
|
||||||
struct {
|
struct {
|
||||||
int exitKey; // Default exit key
|
int exitKey; // Default exit key
|
||||||
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
||||||
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
||||||
|
|
||||||
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
|
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
|
||||||
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
|
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
|
||||||
|
|
||||||
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
|
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
|
||||||
int keyPressedQueueCount; // Input keys queue count
|
int keyPressedQueueCount; // Input keys queue count
|
||||||
|
|
||||||
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
|
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
|
||||||
int charPressedQueueCount; // Input characters queue count
|
int charPressedQueueCount; // Input characters queue count
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
int defaultMode; // Default keyboard mode
|
|
||||||
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
|
||||||
bool evtMode; // Keyboard in event mode
|
|
||||||
#endif
|
|
||||||
int defaultFileFlags; // Default IO file flags
|
|
||||||
struct termios defaultSettings; // Default keyboard settings
|
|
||||||
int fd; // File descriptor for the evdev keyboard
|
|
||||||
#endif
|
|
||||||
} Keyboard;
|
} Keyboard;
|
||||||
struct {
|
struct {
|
||||||
Vector2 offset; // Mouse offset
|
Vector2 offset; // Mouse offset
|
||||||
|
@ -269,11 +169,7 @@ typedef struct CoreData {
|
||||||
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
|
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
|
||||||
Vector2 currentWheelMove; // Registers current mouse wheel variation
|
Vector2 currentWheelMove; // Registers current mouse wheel variation
|
||||||
Vector2 previousWheelMove; // Registers previous mouse wheel variation
|
Vector2 previousWheelMove; // Registers previous mouse wheel variation
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
Vector2 eventWheelMove; // Registers the event mouse wheel variation
|
|
||||||
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
|
|
||||||
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
|
|
||||||
#endif
|
|
||||||
} Mouse;
|
} Mouse;
|
||||||
struct {
|
struct {
|
||||||
int pointCount; // Number of touch points active
|
int pointCount; // Number of touch points active
|
||||||
|
@ -281,6 +177,7 @@ typedef struct CoreData {
|
||||||
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||||
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
||||||
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
||||||
|
|
||||||
} Touch;
|
} Touch;
|
||||||
struct {
|
struct {
|
||||||
int lastButtonPressed; // Register last gamepad button pressed
|
int lastButtonPressed; // Register last gamepad button pressed
|
||||||
|
@ -290,10 +187,7 @@ typedef struct CoreData {
|
||||||
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
||||||
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
||||||
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
pthread_t threadId; // Gamepad reading thread id
|
|
||||||
int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
|
|
||||||
#endif
|
|
||||||
} Gamepad;
|
} Gamepad;
|
||||||
} Input;
|
} Input;
|
||||||
struct {
|
struct {
|
||||||
|
@ -303,10 +197,9 @@ typedef struct CoreData {
|
||||||
double draw; // Time measure for frame draw
|
double draw; // Time measure for frame draw
|
||||||
double frame; // Time measure for one frame
|
double frame; // Time measure for one frame
|
||||||
double target; // Desired time for one frame, if 0 not applied
|
double target; // Desired time for one frame, if 0 not applied
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
unsigned long long int base; // Base time measure for hi-res timer (PLATFORM_ANDROID, PLATFORM_DRM)
|
||||||
unsigned long long int base; // Base time measure for hi-res timer
|
|
||||||
#endif
|
|
||||||
unsigned int frameCounter; // Frame counter
|
unsigned int frameCounter; // Frame counter
|
||||||
|
|
||||||
} Time;
|
} Time;
|
||||||
} CoreData;
|
} CoreData;
|
||||||
|
|
||||||
|
|
|
@ -53,15 +53,31 @@
|
||||||
#include <android_native_app_glue.h> // Required for: android_app struct and activity management
|
#include <android_native_app_glue.h> // Required for: android_app struct and activity management
|
||||||
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL()]
|
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL()]
|
||||||
|
|
||||||
|
#include <EGL/egl.h> // Native platform windowing system interface
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//...
|
typedef struct {
|
||||||
|
// Application data
|
||||||
|
struct android_app *app; // Android activity
|
||||||
|
struct android_poll_source *source; // Android events polling source
|
||||||
|
bool appEnabled; // Flag to detect if app is active ** = true
|
||||||
|
bool contextRebindRequired; // Used to know context rebind 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
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
extern CoreData CORE; // Global CORE state context
|
extern CoreData CORE; // Global CORE state context
|
||||||
|
|
||||||
|
static PlatformData platform = { 0 }; // Platform specific data
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
|
@ -89,7 +105,7 @@ extern int main(int argc, char *argv[]);
|
||||||
void android_main(struct android_app *app)
|
void android_main(struct android_app *app)
|
||||||
{
|
{
|
||||||
char arg0[] = "raylib"; // NOTE: argv[] are mutable
|
char arg0[] = "raylib"; // NOTE: argv[] are mutable
|
||||||
CORE.Android.app = app;
|
platform.app = app;
|
||||||
|
|
||||||
// NOTE: Return from main is ignored
|
// NOTE: Return from main is ignored
|
||||||
(void)main(1, (char *[]) { arg0, NULL });
|
(void)main(1, (char *[]) { arg0, NULL });
|
||||||
|
@ -104,9 +120,9 @@ void android_main(struct android_app *app)
|
||||||
// Waiting for application events before complete finishing
|
// Waiting for application events before complete finishing
|
||||||
while (!app->destroyRequested)
|
while (!app->destroyRequested)
|
||||||
{
|
{
|
||||||
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&CORE.Android.source)) >= 0)
|
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&platform.source)) >= 0)
|
||||||
{
|
{
|
||||||
if (CORE.Android.source != NULL) CORE.Android.source->process(app, CORE.Android.source);
|
if (platform.source != NULL) platform.source->process(app, platform.source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +130,7 @@ void android_main(struct android_app *app)
|
||||||
// NOTE: Add this to header (if apps really need it)
|
// NOTE: Add this to header (if apps really need it)
|
||||||
struct android_app *GetAndroidApp(void)
|
struct android_app *GetAndroidApp(void)
|
||||||
{
|
{
|
||||||
return CORE.Android.app;
|
return platform.app;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize window and OpenGL context
|
// Initialize window and OpenGL context
|
||||||
|
@ -169,9 +185,9 @@ void InitWindow(int width, int height, const char *title)
|
||||||
CORE.Window.currentFbo.height = height;
|
CORE.Window.currentFbo.height = height;
|
||||||
|
|
||||||
// Set desired windows flags before initializing anything
|
// Set desired windows flags before initializing anything
|
||||||
ANativeActivity_setWindowFlags(CORE.Android.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
ANativeActivity_setWindowFlags(platform.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
||||||
|
|
||||||
int orientation = AConfiguration_getOrientation(CORE.Android.app->config);
|
int orientation = AConfiguration_getOrientation(platform.app->config);
|
||||||
|
|
||||||
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as portrait");
|
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as portrait");
|
||||||
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as landscape");
|
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as landscape");
|
||||||
|
@ -179,32 +195,32 @@ void InitWindow(int width, int height, const char *title)
|
||||||
// TODO: Automatic orientation doesn't seem to work
|
// TODO: Automatic orientation doesn't seem to work
|
||||||
if (width <= height)
|
if (width <= height)
|
||||||
{
|
{
|
||||||
AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_PORT);
|
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_PORT);
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
|
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_LAND);
|
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_LAND);
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
|
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
|
||||||
}
|
}
|
||||||
|
|
||||||
//AConfiguration_getDensity(CORE.Android.app->config);
|
//AConfiguration_getDensity(platform.app->config);
|
||||||
//AConfiguration_getKeyboard(CORE.Android.app->config);
|
//AConfiguration_getKeyboard(platform.app->config);
|
||||||
//AConfiguration_getScreenSize(CORE.Android.app->config);
|
//AConfiguration_getScreenSize(platform.app->config);
|
||||||
//AConfiguration_getScreenLong(CORE.Android.app->config);
|
//AConfiguration_getScreenLong(platform.app->config);
|
||||||
|
|
||||||
// Initialize App command system
|
// Initialize App command system
|
||||||
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
|
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
|
||||||
CORE.Android.app->onAppCmd = AndroidCommandCallback;
|
platform.app->onAppCmd = AndroidCommandCallback;
|
||||||
|
|
||||||
// Initialize input events system
|
// Initialize input events system
|
||||||
CORE.Android.app->onInputEvent = AndroidInputCallback;
|
platform.app->onInputEvent = AndroidInputCallback;
|
||||||
|
|
||||||
// Initialize assets manager
|
// Initialize assets manager
|
||||||
InitAssetManager(CORE.Android.app->activity->assetManager, CORE.Android.app->activity->internalDataPath);
|
InitAssetManager(platform.app->activity->assetManager, platform.app->activity->internalDataPath);
|
||||||
|
|
||||||
// Initialize base path for storage
|
// Initialize base path for storage
|
||||||
CORE.Storage.basePath = CORE.Android.app->activity->internalDataPath;
|
CORE.Storage.basePath = platform.app->activity->internalDataPath;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "ANDROID: App initialized successfully");
|
TRACELOG(LOG_INFO, "ANDROID: App initialized successfully");
|
||||||
|
|
||||||
|
@ -216,13 +232,13 @@ void InitWindow(int width, int height, const char *title)
|
||||||
while (!CORE.Window.ready)
|
while (!CORE.Window.ready)
|
||||||
{
|
{
|
||||||
// Process events loop
|
// Process events loop
|
||||||
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0)
|
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)
|
||||||
{
|
{
|
||||||
// Process this event
|
// Process this event
|
||||||
if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source);
|
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
||||||
|
|
||||||
// NOTE: Never close window, native activity is controlled by the system!
|
// NOTE: Never close window, native activity is controlled by the system!
|
||||||
//if (CORE.Android.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,24 +266,24 @@ void CloseWindow(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Close surface, context and display
|
// Close surface, context and display
|
||||||
if (CORE.Window.device != EGL_NO_DISPLAY)
|
if (platform.device != EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
eglMakeCurrent(CORE.Window.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
eglMakeCurrent(platform.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
|
||||||
if (CORE.Window.surface != EGL_NO_SURFACE)
|
if (platform.surface != EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
eglDestroySurface(CORE.Window.device, CORE.Window.surface);
|
eglDestroySurface(platform.device, platform.surface);
|
||||||
CORE.Window.surface = EGL_NO_SURFACE;
|
platform.surface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.context != EGL_NO_CONTEXT)
|
if (platform.context != EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
eglDestroyContext(CORE.Window.device, CORE.Window.context);
|
eglDestroyContext(platform.device, platform.context);
|
||||||
CORE.Window.context = EGL_NO_CONTEXT;
|
platform.context = EGL_NO_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
eglTerminate(CORE.Window.device);
|
eglTerminate(platform.device);
|
||||||
CORE.Window.device = EGL_NO_DISPLAY;
|
platform.device = EGL_NO_DISPLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
@ -306,7 +322,7 @@ bool IsWindowMaximized(void)
|
||||||
// Check if window has the focus
|
// Check if window has the focus
|
||||||
bool IsWindowFocused(void)
|
bool IsWindowFocused(void)
|
||||||
{
|
{
|
||||||
return CORE.Android.appEnabled;
|
return platform.appEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window has been resizedLastFrame
|
// Check if window has been resizedLastFrame
|
||||||
|
@ -595,7 +611,7 @@ void OpenURL(const char *url)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JNIEnv *env = NULL;
|
JNIEnv *env = NULL;
|
||||||
JavaVM *vm = CORE.Android.app->activity->vm;
|
JavaVM *vm = platform.app->activity->vm;
|
||||||
(*vm)->AttachCurrentThread(vm, &env, NULL);
|
(*vm)->AttachCurrentThread(vm, &env, NULL);
|
||||||
|
|
||||||
jstring urlString = (*env)->NewStringUTF(env, url);
|
jstring urlString = (*env)->NewStringUTF(env, url);
|
||||||
|
@ -612,7 +628,7 @@ void OpenURL(const char *url)
|
||||||
(*env)->CallVoidMethod(env, intent, newIntent, actionView, uri);
|
(*env)->CallVoidMethod(env, intent, newIntent, actionView, uri);
|
||||||
jclass activityClass = (*env)->FindClass(env, "android/app/Activity");
|
jclass activityClass = (*env)->FindClass(env, "android/app/Activity");
|
||||||
jmethodID startActivity = (*env)->GetMethodID(env, activityClass, "startActivity", "(Landroid/content/Intent;)V");
|
jmethodID startActivity = (*env)->GetMethodID(env, activityClass, "startActivity", "(Landroid/content/Intent;)V");
|
||||||
(*env)->CallVoidMethod(env, CORE.Android.app->activity->clazz, startActivity, intent);
|
(*env)->CallVoidMethod(env, platform.app->activity->clazz, startActivity, intent);
|
||||||
|
|
||||||
(*vm)->DetachCurrentThread(vm);
|
(*vm)->DetachCurrentThread(vm);
|
||||||
}
|
}
|
||||||
|
@ -713,7 +729,7 @@ Vector2 GetTouchPosition(int index)
|
||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
{
|
{
|
||||||
eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
|
eglSwapBuffers(platform.device, platform.surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
|
@ -756,17 +772,17 @@ void PollInputEvents(void)
|
||||||
int pollEvents = 0;
|
int pollEvents = 0;
|
||||||
|
|
||||||
// Poll Events (registered events)
|
// Poll Events (registered events)
|
||||||
// NOTE: Activity is paused if not enabled (CORE.Android.appEnabled)
|
// NOTE: Activity is paused if not enabled (platform.appEnabled)
|
||||||
while ((pollResult = ALooper_pollAll(CORE.Android.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0)
|
while ((pollResult = ALooper_pollAll(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) >= 0)
|
||||||
{
|
{
|
||||||
// Process this event
|
// Process this event
|
||||||
if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source);
|
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
||||||
|
|
||||||
// NOTE: Never close window, native activity is controlled by the system!
|
// NOTE: Never close window, native activity is controlled by the system!
|
||||||
if (CORE.Android.app->destroyRequested != 0)
|
if (platform.app->destroyRequested != 0)
|
||||||
{
|
{
|
||||||
//CORE.Window.shouldClose = true;
|
//CORE.Window.shouldClose = true;
|
||||||
//ANativeActivity_finish(CORE.Android.app->activity);
|
//ANativeActivity_finish(platform.app->activity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,15 +845,15 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
EGLint numConfigs = 0;
|
EGLint numConfigs = 0;
|
||||||
|
|
||||||
// Get an EGL device connection
|
// Get an EGL device connection
|
||||||
CORE.Window.device = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
platform.device = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
if (CORE.Window.device == EGL_NO_DISPLAY)
|
if (platform.device == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the EGL device connection
|
// Initialize the EGL device connection
|
||||||
if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE)
|
if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE)
|
||||||
{
|
{
|
||||||
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
|
@ -845,14 +861,14 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an appropriate EGL framebuffer configuration
|
// Get an appropriate EGL framebuffer configuration
|
||||||
eglChooseConfig(CORE.Window.device, framebufferAttribs, &CORE.Window.config, 1, &numConfigs);
|
eglChooseConfig(platform.device, framebufferAttribs, &platform.config, 1, &numConfigs);
|
||||||
|
|
||||||
// Set rendering API
|
// Set rendering API
|
||||||
eglBindAPI(EGL_OPENGL_ES_API);
|
eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
|
|
||||||
// Create an EGL rendering context
|
// Create an EGL rendering context
|
||||||
CORE.Window.context = eglCreateContext(CORE.Window.device, CORE.Window.config, EGL_NO_CONTEXT, contextAttribs);
|
platform.context = eglCreateContext(platform.device, platform.config, EGL_NO_CONTEXT, contextAttribs);
|
||||||
if (CORE.Window.context == EGL_NO_CONTEXT)
|
if (platform.context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
||||||
return false;
|
return false;
|
||||||
|
@ -864,7 +880,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry()
|
// 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
|
// As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID
|
||||||
eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
|
eglGetConfigAttrib(platform.device, platform.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
|
||||||
|
|
||||||
// At this point we need to manage render size vs screen size
|
// At this point we need to manage render size vs screen size
|
||||||
// NOTE: This function use and modify global module variables:
|
// NOTE: This function use and modify global module variables:
|
||||||
|
@ -873,15 +889,15 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// -> CORE.Window.screenScale
|
// -> CORE.Window.screenScale
|
||||||
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||||
|
|
||||||
ANativeWindow_setBuffersGeometry(CORE.Android.app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat);
|
ANativeWindow_setBuffersGeometry(platform.app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat);
|
||||||
//ANativeWindow_setBuffersGeometry(CORE.Android.app->window, 0, 0, displayFormat); // Force use of native display size
|
//ANativeWindow_setBuffersGeometry(platform.app->window, 0, 0, displayFormat); // Force use of native display size
|
||||||
|
|
||||||
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, CORE.Android.app->window, NULL);
|
platform.surface = eglCreateWindowSurface(platform.device, platform.config, platform.app->window, NULL);
|
||||||
|
|
||||||
// There must be at least one frame displayed before the buffers are swapped
|
// There must be at least one frame displayed before the buffers are swapped
|
||||||
//eglSwapInterval(CORE.Window.device, 1);
|
//eglSwapInterval(platform.device, 1);
|
||||||
|
|
||||||
if (eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context) == EGL_FALSE)
|
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");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
||||||
return false;
|
return false;
|
||||||
|
@ -933,11 +949,11 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
{
|
{
|
||||||
if (app->window != NULL)
|
if (app->window != NULL)
|
||||||
{
|
{
|
||||||
if (CORE.Android.contextRebindRequired)
|
if (platform.contextRebindRequired)
|
||||||
{
|
{
|
||||||
// Reset screen scaling to full display size
|
// Reset screen scaling to full display size
|
||||||
EGLint displayFormat = 0;
|
EGLint displayFormat = 0;
|
||||||
eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
|
eglGetConfigAttrib(platform.device, platform.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
|
||||||
|
|
||||||
// Adding renderOffset here feels rather hackish, but the viewport scaling is wrong after the
|
// Adding renderOffset here feels rather hackish, but the viewport scaling is wrong after the
|
||||||
// context rebinding if the screen is scaled unless offsets are added. There's probably a more
|
// context rebinding if the screen is scaled unless offsets are added. There's probably a more
|
||||||
|
@ -948,15 +964,15 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
displayFormat);
|
displayFormat);
|
||||||
|
|
||||||
// Recreate display surface and re-attach OpenGL context
|
// Recreate display surface and re-attach OpenGL context
|
||||||
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, app->window, NULL);
|
platform.surface = eglCreateWindowSurface(platform.device, platform.config, app->window, NULL);
|
||||||
eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context);
|
eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context);
|
||||||
|
|
||||||
CORE.Android.contextRebindRequired = false;
|
platform.contextRebindRequired = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CORE.Window.display.width = ANativeWindow_getWidth(CORE.Android.app->window);
|
CORE.Window.display.width = ANativeWindow_getWidth(platform.app->window);
|
||||||
CORE.Window.display.height = ANativeWindow_getHeight(CORE.Android.app->window);
|
CORE.Window.display.height = ANativeWindow_getHeight(platform.app->window);
|
||||||
|
|
||||||
// Initialize graphics device (display device and OpenGL context)
|
// Initialize graphics device (display device and OpenGL context)
|
||||||
InitGraphicsDevice(CORE.Window.screen.width, CORE.Window.screen.height);
|
InitGraphicsDevice(CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
|
@ -997,13 +1013,13 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
} break;
|
} break;
|
||||||
case APP_CMD_GAINED_FOCUS:
|
case APP_CMD_GAINED_FOCUS:
|
||||||
{
|
{
|
||||||
CORE.Android.appEnabled = true;
|
platform.appEnabled = true;
|
||||||
//ResumeMusicStream();
|
//ResumeMusicStream();
|
||||||
} break;
|
} break;
|
||||||
case APP_CMD_PAUSE: break;
|
case APP_CMD_PAUSE: break;
|
||||||
case APP_CMD_LOST_FOCUS:
|
case APP_CMD_LOST_FOCUS:
|
||||||
{
|
{
|
||||||
CORE.Android.appEnabled = false;
|
platform.appEnabled = false;
|
||||||
//PauseMusicStream();
|
//PauseMusicStream();
|
||||||
} break;
|
} break;
|
||||||
case APP_CMD_TERM_WINDOW:
|
case APP_CMD_TERM_WINDOW:
|
||||||
|
@ -1012,19 +1028,19 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
// NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming.
|
// NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming.
|
||||||
// NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
|
// NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
|
||||||
// NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
|
// NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
|
||||||
if (CORE.Window.device != EGL_NO_DISPLAY)
|
if (platform.device != EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
eglMakeCurrent(CORE.Window.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
eglMakeCurrent(platform.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
|
||||||
if (CORE.Window.surface != EGL_NO_SURFACE)
|
if (platform.surface != EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
eglDestroySurface(CORE.Window.device, CORE.Window.surface);
|
eglDestroySurface(platform.device, platform.surface);
|
||||||
CORE.Window.surface = EGL_NO_SURFACE;
|
platform.surface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Android.contextRebindRequired = true;
|
platform.contextRebindRequired = true;
|
||||||
}
|
}
|
||||||
// If 'CORE.Window.device' is already set to 'EGL_NO_DISPLAY'
|
// If 'platform.device' is already set to 'EGL_NO_DISPLAY'
|
||||||
// this means that the user has already called 'CloseWindow()'
|
// this means that the user has already called 'CloseWindow()'
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1033,8 +1049,8 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
case APP_CMD_DESTROY: break;
|
case APP_CMD_DESTROY: break;
|
||||||
case APP_CMD_CONFIG_CHANGED:
|
case APP_CMD_CONFIG_CHANGED:
|
||||||
{
|
{
|
||||||
//AConfiguration_fromAssetManager(CORE.Android.app->config, CORE.Android.app->activity->assetManager);
|
//AConfiguration_fromAssetManager(platform.app->config, platform.app->activity->assetManager);
|
||||||
//print_cur_config(CORE.Android.app);
|
//print_cur_config(platform.app);
|
||||||
|
|
||||||
// Check screen orientation here!
|
// Check screen orientation here!
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -85,15 +85,28 @@
|
||||||
#include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()
|
#include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// TODO: HACK: Added flag if not provided by GLFW when using external library
|
||||||
|
// Latest GLFW release (GLFW 3.3.8) does not implement this flag, it was added for 3.4.0-dev
|
||||||
|
#if !defined(GLFW_MOUSE_PASSTHROUGH)
|
||||||
|
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//...
|
typedef struct {
|
||||||
|
GLFWwindow *handle; // GLFW window handle (graphic device)
|
||||||
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
extern CoreData CORE; // Global CORE state context
|
extern CoreData CORE; // Global CORE state context
|
||||||
|
|
||||||
|
static PlatformData platform = { 0 }; // Platform specific data
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
|
@ -255,7 +268,7 @@ void CloseWindow(void)
|
||||||
|
|
||||||
rlglClose(); // De-init rlgl
|
rlglClose(); // De-init rlgl
|
||||||
|
|
||||||
glfwDestroyWindow(CORE.Window.handle);
|
glfwDestroyWindow(platform.handle);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
||||||
|
@ -279,10 +292,10 @@ bool WindowShouldClose(void)
|
||||||
// While window minimized, stop loop execution
|
// While window minimized, stop loop execution
|
||||||
while (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) glfwWaitEvents();
|
while (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) glfwWaitEvents();
|
||||||
|
|
||||||
CORE.Window.shouldClose = glfwWindowShouldClose(CORE.Window.handle);
|
CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);
|
||||||
|
|
||||||
// Reset close status for next frame
|
// Reset close status for next frame
|
||||||
glfwSetWindowShouldClose(CORE.Window.handle, GLFW_FALSE);
|
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
|
||||||
|
|
||||||
return CORE.Window.shouldClose;
|
return CORE.Window.shouldClose;
|
||||||
}
|
}
|
||||||
|
@ -325,7 +338,7 @@ void ToggleFullscreen(void)
|
||||||
if (!CORE.Window.fullscreen)
|
if (!CORE.Window.fullscreen)
|
||||||
{
|
{
|
||||||
// Store previous window position (in case we exit fullscreen)
|
// Store previous window position (in case we exit fullscreen)
|
||||||
glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y);
|
glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y);
|
||||||
|
|
||||||
int monitorCount = 0;
|
int monitorCount = 0;
|
||||||
int monitorIndex = GetCurrentMonitor();
|
int monitorIndex = GetCurrentMonitor();
|
||||||
|
@ -341,14 +354,14 @@ void ToggleFullscreen(void)
|
||||||
CORE.Window.fullscreen = false;
|
CORE.Window.fullscreen = false;
|
||||||
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
glfwSetWindowMonitor(CORE.Window.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
glfwSetWindowMonitor(platform.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CORE.Window.fullscreen = true;
|
CORE.Window.fullscreen = true;
|
||||||
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
glfwSetWindowMonitor(CORE.Window.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
glfwSetWindowMonitor(platform.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -357,7 +370,7 @@ void ToggleFullscreen(void)
|
||||||
CORE.Window.fullscreen = false;
|
CORE.Window.fullscreen = false;
|
||||||
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
||||||
|
@ -368,9 +381,9 @@ void ToggleFullscreen(void)
|
||||||
// Set window state: maximized, if resizable
|
// Set window state: maximized, if resizable
|
||||||
void MaximizeWindow(void)
|
void MaximizeWindow(void)
|
||||||
{
|
{
|
||||||
if (glfwGetWindowAttrib(CORE.Window.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
||||||
{
|
{
|
||||||
glfwMaximizeWindow(CORE.Window.handle);
|
glfwMaximizeWindow(platform.handle);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,16 +392,16 @@ void MaximizeWindow(void)
|
||||||
void MinimizeWindow(void)
|
void MinimizeWindow(void)
|
||||||
{
|
{
|
||||||
// NOTE: Following function launches callback that sets appropriate flag!
|
// NOTE: Following function launches callback that sets appropriate flag!
|
||||||
glfwIconifyWindow(CORE.Window.handle);
|
glfwIconifyWindow(platform.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window state: not minimized/maximized
|
// Set window state: not minimized/maximized
|
||||||
void RestoreWindow(void)
|
void RestoreWindow(void)
|
||||||
{
|
{
|
||||||
if (glfwGetWindowAttrib(CORE.Window.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
||||||
{
|
{
|
||||||
// Restores the specified window if it was previously iconified (minimized) or maximized
|
// Restores the specified window if it was previously iconified (minimized) or maximized
|
||||||
glfwRestoreWindow(CORE.Window.handle);
|
glfwRestoreWindow(platform.handle);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
|
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
|
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
|
||||||
}
|
}
|
||||||
|
@ -420,13 +433,13 @@ void ToggleBorderlessWindowed(void)
|
||||||
{
|
{
|
||||||
// Store screen position and size
|
// Store screen position and size
|
||||||
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
|
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
|
||||||
if (!wasOnFullscreen) glfwGetWindowPos(CORE.Window.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y);
|
if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y);
|
||||||
CORE.Window.previousScreen = CORE.Window.screen;
|
CORE.Window.previousScreen = CORE.Window.screen;
|
||||||
|
|
||||||
// Set undecorated and topmost modes and flags
|
// Set undecorated and topmost modes and flags
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_DECORATED, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
|
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FLOATING, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;
|
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;
|
||||||
|
|
||||||
// Get monitor position and size
|
// Get monitor position and size
|
||||||
|
@ -437,29 +450,29 @@ void ToggleBorderlessWindowed(void)
|
||||||
const int monitorHeight = mode->height;
|
const int monitorHeight = mode->height;
|
||||||
|
|
||||||
// Set screen position and size
|
// Set screen position and size
|
||||||
glfwSetWindowPos(CORE.Window.handle, monitorPosX, monitorPosY);
|
glfwSetWindowPos(platform.handle, monitorPosX, monitorPosY);
|
||||||
glfwSetWindowSize(CORE.Window.handle, monitorWidth, monitorHeight);
|
glfwSetWindowSize(platform.handle, monitorWidth, monitorHeight);
|
||||||
|
|
||||||
// Refocus window
|
// Refocus window
|
||||||
glfwFocusWindow(CORE.Window.handle);
|
glfwFocusWindow(platform.handle);
|
||||||
|
|
||||||
CORE.Window.flags |= FLAG_BORDERLESS_WINDOWED_MODE;
|
CORE.Window.flags |= FLAG_BORDERLESS_WINDOWED_MODE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Remove topmost and undecorated modes and flags
|
// Remove topmost and undecorated modes and flags
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FLOATING, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
|
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_DECORATED, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;
|
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;
|
||||||
|
|
||||||
// Return previous screen size and position
|
// Return previous screen size and position
|
||||||
// NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly
|
// NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly
|
||||||
glfwSetWindowSize(CORE.Window.handle, CORE.Window.previousScreen.width, CORE.Window.previousScreen.height);
|
glfwSetWindowSize(platform.handle, CORE.Window.previousScreen.width, CORE.Window.previousScreen.height);
|
||||||
glfwSetWindowPos(CORE.Window.handle, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y);
|
glfwSetWindowPos(platform.handle, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y);
|
||||||
|
|
||||||
// Refocus window
|
// Refocus window
|
||||||
glfwFocusWindow(CORE.Window.handle);
|
glfwFocusWindow(platform.handle);
|
||||||
|
|
||||||
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
|
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
|
||||||
}
|
}
|
||||||
|
@ -498,21 +511,21 @@ void SetWindowState(unsigned int flags)
|
||||||
// State change: FLAG_WINDOW_RESIZABLE
|
// State change: FLAG_WINDOW_RESIZABLE
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) != (flags & FLAG_WINDOW_RESIZABLE)) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) != (flags & FLAG_WINDOW_RESIZABLE)) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_RESIZABLE, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_TRUE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_RESIZABLE;
|
CORE.Window.flags |= FLAG_WINDOW_RESIZABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_UNDECORATED
|
// State change: FLAG_WINDOW_UNDECORATED
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) != (flags & FLAG_WINDOW_UNDECORATED)) && (flags & FLAG_WINDOW_UNDECORATED))
|
if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) != (flags & FLAG_WINDOW_UNDECORATED)) && (flags & FLAG_WINDOW_UNDECORATED))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_DECORATED, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
|
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_HIDDEN
|
// State change: FLAG_WINDOW_HIDDEN
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) != (flags & FLAG_WINDOW_HIDDEN)) && ((flags & FLAG_WINDOW_HIDDEN) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) != (flags & FLAG_WINDOW_HIDDEN)) && ((flags & FLAG_WINDOW_HIDDEN) > 0))
|
||||||
{
|
{
|
||||||
glfwHideWindow(CORE.Window.handle);
|
glfwHideWindow(platform.handle);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_HIDDEN;
|
CORE.Window.flags |= FLAG_WINDOW_HIDDEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,14 +546,14 @@ void SetWindowState(unsigned int flags)
|
||||||
// State change: FLAG_WINDOW_UNFOCUSED
|
// State change: FLAG_WINDOW_UNFOCUSED
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) != (flags & FLAG_WINDOW_UNFOCUSED)) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) != (flags & FLAG_WINDOW_UNFOCUSED)) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
|
CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_TOPMOST
|
// State change: FLAG_WINDOW_TOPMOST
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) != (flags & FLAG_WINDOW_TOPMOST)) && ((flags & FLAG_WINDOW_TOPMOST) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) != (flags & FLAG_WINDOW_TOPMOST)) && ((flags & FLAG_WINDOW_TOPMOST) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FLOATING, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;
|
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +580,7 @@ void SetWindowState(unsigned int flags)
|
||||||
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) != (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) != (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
|
||||||
CORE.Window.flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH;
|
CORE.Window.flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,14 +626,14 @@ void ClearWindowState(unsigned int flags)
|
||||||
// State change: FLAG_WINDOW_RESIZABLE
|
// State change: FLAG_WINDOW_RESIZABLE
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_RESIZABLE, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_RESIZABLE;
|
CORE.Window.flags &= ~FLAG_WINDOW_RESIZABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_HIDDEN
|
// State change: FLAG_WINDOW_HIDDEN
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) && ((flags & FLAG_WINDOW_HIDDEN) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) && ((flags & FLAG_WINDOW_HIDDEN) > 0))
|
||||||
{
|
{
|
||||||
glfwShowWindow(CORE.Window.handle);
|
glfwShowWindow(platform.handle);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;
|
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,21 +652,21 @@ void ClearWindowState(unsigned int flags)
|
||||||
// State change: FLAG_WINDOW_UNDECORATED
|
// State change: FLAG_WINDOW_UNDECORATED
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) && ((flags & FLAG_WINDOW_UNDECORATED) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) && ((flags & FLAG_WINDOW_UNDECORATED) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_DECORATED, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;
|
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_UNFOCUSED
|
// State change: FLAG_WINDOW_UNFOCUSED
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FOCUS_ON_SHOW, GLFW_TRUE);
|
glfwSetWindowAttrib(platform.handle, GLFW_FOCUS_ON_SHOW, GLFW_TRUE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
|
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_TOPMOST
|
// State change: FLAG_WINDOW_TOPMOST
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) && ((flags & FLAG_WINDOW_TOPMOST) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) && ((flags & FLAG_WINDOW_TOPMOST) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FLOATING, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
|
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,7 +693,7 @@ void ClearWindowState(unsigned int flags)
|
||||||
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
||||||
if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
|
if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
|
||||||
{
|
{
|
||||||
glfwSetWindowAttrib(CORE.Window.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
|
glfwSetWindowAttrib(platform.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_MOUSE_PASSTHROUGH;
|
CORE.Window.flags &= ~FLAG_WINDOW_MOUSE_PASSTHROUGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,7 +718,7 @@ void SetWindowIcon(Image image)
|
||||||
if (image.data == NULL)
|
if (image.data == NULL)
|
||||||
{
|
{
|
||||||
// Revert to the default window icon, pass in an empty image array
|
// Revert to the default window icon, pass in an empty image array
|
||||||
glfwSetWindowIcon(CORE.Window.handle, 0, NULL);
|
glfwSetWindowIcon(platform.handle, 0, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -719,7 +732,7 @@ void SetWindowIcon(Image image)
|
||||||
|
|
||||||
// NOTE 1: We only support one image icon
|
// NOTE 1: We only support one image icon
|
||||||
// NOTE 2: The specified image data is copied before this function returns
|
// NOTE 2: The specified image data is copied before this function returns
|
||||||
glfwSetWindowIcon(CORE.Window.handle, 1, icon);
|
glfwSetWindowIcon(platform.handle, 1, icon);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
||||||
}
|
}
|
||||||
|
@ -734,7 +747,7 @@ void SetWindowIcons(Image *images, int count)
|
||||||
if ((images == NULL) || (count <= 0))
|
if ((images == NULL) || (count <= 0))
|
||||||
{
|
{
|
||||||
// Revert to the default window icon, pass in an empty image array
|
// Revert to the default window icon, pass in an empty image array
|
||||||
glfwSetWindowIcon(CORE.Window.handle, 0, NULL);
|
glfwSetWindowIcon(platform.handle, 0, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -754,7 +767,7 @@ void SetWindowIcons(Image *images, int count)
|
||||||
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
||||||
}
|
}
|
||||||
// NOTE: Images data is copied internally before this function returns
|
// NOTE: Images data is copied internally before this function returns
|
||||||
glfwSetWindowIcon(CORE.Window.handle, valid, icons);
|
glfwSetWindowIcon(platform.handle, valid, icons);
|
||||||
|
|
||||||
RL_FREE(icons);
|
RL_FREE(icons);
|
||||||
}
|
}
|
||||||
|
@ -764,13 +777,13 @@ void SetWindowIcons(Image *images, int count)
|
||||||
void SetWindowTitle(const char *title)
|
void SetWindowTitle(const char *title)
|
||||||
{
|
{
|
||||||
CORE.Window.title = title;
|
CORE.Window.title = title;
|
||||||
glfwSetWindowTitle(CORE.Window.handle, title);
|
glfwSetWindowTitle(platform.handle, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window position on screen (windowed mode)
|
// Set window position on screen (windowed mode)
|
||||||
void SetWindowPosition(int x, int y)
|
void SetWindowPosition(int x, int y)
|
||||||
{
|
{
|
||||||
glfwSetWindowPos(CORE.Window.handle, x, y);
|
glfwSetWindowPos(platform.handle, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set monitor for the current window
|
// Set monitor for the current window
|
||||||
|
@ -786,7 +799,7 @@ void SetWindowMonitor(int monitor)
|
||||||
TRACELOG(LOG_INFO, "GLFW: Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
|
TRACELOG(LOG_INFO, "GLFW: Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
|
||||||
|
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
|
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
|
||||||
glfwSetWindowMonitor(CORE.Window.handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate);
|
glfwSetWindowMonitor(platform.handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -801,12 +814,12 @@ void SetWindowMonitor(int monitor)
|
||||||
glfwGetMonitorWorkarea(monitors[monitor], &monitorWorkareaX, &monitorWorkareaY, &monitorWorkareaWidth, &monitorWorkareaHeight);
|
glfwGetMonitorWorkarea(monitors[monitor], &monitorWorkareaX, &monitorWorkareaY, &monitorWorkareaWidth, &monitorWorkareaHeight);
|
||||||
|
|
||||||
// If the screen size is larger than the monitor workarea, anchor it on the top left corner, otherwise, center it
|
// If the screen size is larger than the monitor workarea, anchor it on the top left corner, otherwise, center it
|
||||||
if ((screenWidth >= monitorWorkareaWidth) || (screenHeight >= monitorWorkareaHeight)) glfwSetWindowPos(CORE.Window.handle, monitorWorkareaX, monitorWorkareaY);
|
if ((screenWidth >= monitorWorkareaWidth) || (screenHeight >= monitorWorkareaHeight)) glfwSetWindowPos(platform.handle, monitorWorkareaX, monitorWorkareaY);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const int x = monitorWorkareaX + (monitorWorkareaWidth/2) - (screenWidth/2);
|
const int x = monitorWorkareaX + (monitorWorkareaWidth/2) - (screenWidth/2);
|
||||||
const int y = monitorWorkareaY + (monitorWorkareaHeight/2) - (screenHeight/2);
|
const int y = monitorWorkareaY + (monitorWorkareaHeight/2) - (screenHeight/2);
|
||||||
glfwSetWindowPos(CORE.Window.handle, x, y);
|
glfwSetWindowPos(platform.handle, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -822,7 +835,7 @@ void SetWindowMinSize(int width, int height)
|
||||||
int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMin.height;
|
int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMin.height;
|
||||||
int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.width;
|
int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.width;
|
||||||
int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.height;
|
int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.height;
|
||||||
glfwSetWindowSizeLimits(CORE.Window.handle, minWidth, minHeight, maxWidth, maxHeight);
|
glfwSetWindowSizeLimits(platform.handle, minWidth, minHeight, maxWidth, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
|
@ -834,13 +847,13 @@ void SetWindowMaxSize(int width, int height)
|
||||||
int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMin.height;
|
int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMin.height;
|
||||||
int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.width;
|
int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.width;
|
||||||
int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.height;
|
int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : CORE.Window.screenMax.height;
|
||||||
glfwSetWindowSizeLimits(CORE.Window.handle, minWidth, minHeight, maxWidth, maxHeight);
|
glfwSetWindowSizeLimits(platform.handle, minWidth, minHeight, maxWidth, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window dimensions
|
// Set window dimensions
|
||||||
void SetWindowSize(int width, int height)
|
void SetWindowSize(int width, int height)
|
||||||
{
|
{
|
||||||
glfwSetWindowSize(CORE.Window.handle, width, height);
|
glfwSetWindowSize(platform.handle, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window opacity, value opacity is between 0.0 and 1.0
|
// Set window opacity, value opacity is between 0.0 and 1.0
|
||||||
|
@ -848,13 +861,13 @@ void SetWindowOpacity(float opacity)
|
||||||
{
|
{
|
||||||
if (opacity >= 1.0f) opacity = 1.0f;
|
if (opacity >= 1.0f) opacity = 1.0f;
|
||||||
else if (opacity <= 0.0f) opacity = 0.0f;
|
else if (opacity <= 0.0f) opacity = 0.0f;
|
||||||
glfwSetWindowOpacity(CORE.Window.handle, opacity);
|
glfwSetWindowOpacity(platform.handle, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window focused
|
// Set window focused
|
||||||
void SetWindowFocused(void)
|
void SetWindowFocused(void)
|
||||||
{
|
{
|
||||||
glfwFocusWindow(CORE.Window.handle);
|
glfwFocusWindow(platform.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get native window handle
|
// Get native window handle
|
||||||
|
@ -862,19 +875,19 @@ void *GetWindowHandle(void)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// NOTE: Returned handle is: void *HWND (windows.h)
|
// NOTE: Returned handle is: void *HWND (windows.h)
|
||||||
return glfwGetWin32Window(CORE.Window.handle);
|
return glfwGetWin32Window(platform.handle);
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
// NOTE: Returned handle is: unsigned long Window (X.h)
|
// NOTE: Returned handle is: unsigned long Window (X.h)
|
||||||
// typedef unsigned long XID;
|
// typedef unsigned long XID;
|
||||||
// typedef XID Window;
|
// typedef XID Window;
|
||||||
//unsigned long id = (unsigned long)glfwGetX11Window(CORE.Window.handle);
|
//unsigned long id = (unsigned long)glfwGetX11Window(platform.handle);
|
||||||
//return NULL; // TODO: Find a way to return value... cast to void *?
|
//return NULL; // TODO: Find a way to return value... cast to void *?
|
||||||
return (void *)CORE.Window.handle;
|
return (void *)platform.handle;
|
||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
// NOTE: Returned handle is: (objc_object *)
|
// NOTE: Returned handle is: (objc_object *)
|
||||||
return (void *)glfwGetCocoaWindow(CORE.Window.handle);
|
return (void *)glfwGetCocoaWindow(platform.handle);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -903,7 +916,7 @@ int GetCurrentMonitor(void)
|
||||||
if (IsWindowFullscreen())
|
if (IsWindowFullscreen())
|
||||||
{
|
{
|
||||||
// Get the handle of the monitor that the specified window is in full screen on
|
// Get the handle of the monitor that the specified window is in full screen on
|
||||||
monitor = glfwGetWindowMonitor(CORE.Window.handle);
|
monitor = glfwGetWindowMonitor(platform.handle);
|
||||||
|
|
||||||
for (int i = 0; i < monitorCount; i++)
|
for (int i = 0; i < monitorCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -919,7 +932,7 @@ int GetCurrentMonitor(void)
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
glfwGetWindowPos(CORE.Window.handle, &x, &y);
|
glfwGetWindowPos(platform.handle, &x, &y);
|
||||||
|
|
||||||
for (int i = 0; i < monitorCount; i++)
|
for (int i = 0; i < monitorCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -1070,7 +1083,7 @@ Vector2 GetWindowPosition(void)
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
glfwGetWindowPos(CORE.Window.handle, &x, &y);
|
glfwGetWindowPos(platform.handle, &x, &y);
|
||||||
|
|
||||||
return (Vector2){ (float)x, (float)y };
|
return (Vector2){ (float)x, (float)y };
|
||||||
}
|
}
|
||||||
|
@ -1109,34 +1122,34 @@ Vector2 GetWindowScaleDPI(void)
|
||||||
// Set clipboard text content
|
// Set clipboard text content
|
||||||
void SetClipboardText(const char *text)
|
void SetClipboardText(const char *text)
|
||||||
{
|
{
|
||||||
glfwSetClipboardString(CORE.Window.handle, text);
|
glfwSetClipboardString(platform.handle, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get clipboard text content
|
// Get clipboard text content
|
||||||
// NOTE: returned string is allocated and freed by GLFW
|
// NOTE: returned string is allocated and freed by GLFW
|
||||||
const char *GetClipboardText(void)
|
const char *GetClipboardText(void)
|
||||||
{
|
{
|
||||||
return glfwGetClipboardString(CORE.Window.handle);
|
return glfwGetClipboardString(platform.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show mouse cursor
|
// Show mouse cursor
|
||||||
void ShowCursor(void)
|
void ShowCursor(void)
|
||||||
{
|
{
|
||||||
glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hides mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enables cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
||||||
|
@ -1147,7 +1160,7 @@ void EnableCursor(void)
|
||||||
// Disables cursor (lock cursor)
|
// Disables cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
||||||
|
@ -1276,7 +1289,7 @@ void SetMousePosition(int x, int y)
|
||||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
||||||
// NOTE: emscripten not implemented
|
// NOTE: emscripten not implemented
|
||||||
glfwSetCursorPos(CORE.Window.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
// Get mouse wheel movement Y
|
||||||
|
@ -1294,11 +1307,11 @@ float GetMouseWheelMove(void)
|
||||||
void SetMouseCursor(int cursor)
|
void SetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.cursor = cursor;
|
CORE.Input.Mouse.cursor = cursor;
|
||||||
if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(CORE.Window.handle, NULL);
|
if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: We are relating internal GLFW enum values to our MouseCursor enum values
|
// NOTE: We are relating internal GLFW enum values to our MouseCursor enum values
|
||||||
glfwSetCursor(CORE.Window.handle, glfwCreateStandardCursor(0x00036000 + cursor));
|
glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,7 +1344,7 @@ Vector2 GetTouchPosition(int index)
|
||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
{
|
{
|
||||||
glfwSwapBuffers(CORE.Window.handle);
|
glfwSwapBuffers(platform.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
|
@ -1691,10 +1704,10 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
|
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
|
||||||
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||||
|
|
||||||
CORE.Window.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", glfwGetPrimaryMonitor(), NULL);
|
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", glfwGetPrimaryMonitor(), NULL);
|
||||||
|
|
||||||
// NOTE: Full-screen change, not working properly...
|
// NOTE: Full-screen change, not working properly...
|
||||||
//glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
//glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1705,16 +1718,16 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// No-fullscreen window creation
|
// No-fullscreen window creation
|
||||||
CORE.Window.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
platform.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
||||||
|
|
||||||
if (CORE.Window.handle)
|
if (platform.handle)
|
||||||
{
|
{
|
||||||
CORE.Window.render.width = CORE.Window.screen.width;
|
CORE.Window.render.width = CORE.Window.screen.width;
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CORE.Window.handle)
|
if (!platform.handle)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||||
|
@ -1722,23 +1735,23 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window callback events
|
// Set window callback events
|
||||||
glfwSetWindowSizeCallback(CORE.Window.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
|
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
|
||||||
glfwSetWindowMaximizeCallback(CORE.Window.handle, WindowMaximizeCallback);
|
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
|
||||||
glfwSetWindowIconifyCallback(CORE.Window.handle, WindowIconifyCallback);
|
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
|
||||||
glfwSetWindowFocusCallback(CORE.Window.handle, WindowFocusCallback);
|
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
|
||||||
glfwSetDropCallback(CORE.Window.handle, WindowDropCallback);
|
glfwSetDropCallback(platform.handle, WindowDropCallback);
|
||||||
|
|
||||||
// Set input callback events
|
// Set input callback events
|
||||||
glfwSetKeyCallback(CORE.Window.handle, KeyCallback);
|
glfwSetKeyCallback(platform.handle, KeyCallback);
|
||||||
glfwSetCharCallback(CORE.Window.handle, CharCallback);
|
glfwSetCharCallback(platform.handle, CharCallback);
|
||||||
glfwSetMouseButtonCallback(CORE.Window.handle, MouseButtonCallback);
|
glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback);
|
||||||
glfwSetCursorPosCallback(CORE.Window.handle, MouseCursorPosCallback); // Track mouse position changes
|
glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes
|
||||||
glfwSetScrollCallback(CORE.Window.handle, MouseScrollCallback);
|
glfwSetScrollCallback(platform.handle, MouseScrollCallback);
|
||||||
glfwSetCursorEnterCallback(CORE.Window.handle, CursorEnterCallback);
|
glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);
|
||||||
|
|
||||||
glfwMakeContextCurrent(CORE.Window.handle);
|
glfwMakeContextCurrent(platform.handle);
|
||||||
|
|
||||||
glfwSetInputMode(CORE.Window.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)
|
glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)
|
||||||
|
|
||||||
glfwSwapInterval(0); // No V-Sync by default
|
glfwSwapInterval(0); // No V-Sync by default
|
||||||
|
|
||||||
|
@ -1760,7 +1773,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
|
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
|
||||||
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||||
#if !defined(__APPLE__)
|
#if !defined(__APPLE__)
|
||||||
glfwGetFramebufferSize(CORE.Window.handle, &fbWidth, &fbHeight);
|
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
|
||||||
|
|
||||||
// Screen scaling matrix is required in case desired screen area is different from display area
|
// Screen scaling matrix is required in case desired screen area is different from display area
|
||||||
CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
|
CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
|
||||||
|
@ -1913,7 +1926,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the exit key to set close window
|
// Check the exit key to set close window
|
||||||
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(CORE.Window.handle, GLFW_TRUE);
|
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(platform.handle, GLFW_TRUE);
|
||||||
|
|
||||||
#if defined(SUPPORT_SCREEN_CAPTURE)
|
#if defined(SUPPORT_SCREEN_CAPTURE)
|
||||||
if ((key == GLFW_KEY_F12) && (action == GLFW_PRESS))
|
if ((key == GLFW_KEY_F12) && (action == GLFW_PRESS))
|
||||||
|
|
398
src/rcore_drm.c
398
src/rcore_drm.c
|
@ -17,8 +17,10 @@
|
||||||
* - TRACELOG() function is located in raylib [utils] module
|
* - TRACELOG() function is located in raylib [utils] module
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define RCORE_DRM_CUSTOM_FLAG
|
* #define SUPPORT_SSH_KEYBOARD_RPI (Raspberry Pi only)
|
||||||
* Custom flag for rcore on PLATFORM_DRM -not used-
|
* Reconfigure standard input to receive key inputs, works with SSH connection.
|
||||||
|
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other
|
||||||
|
* running processes orblocking the device if not restored properly. Use with care.
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs)
|
* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs)
|
||||||
|
@ -47,15 +49,93 @@
|
||||||
|
|
||||||
#include "rcore.h"
|
#include "rcore.h"
|
||||||
|
|
||||||
|
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
||||||
|
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
||||||
|
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
||||||
|
#include <pthread.h> // POSIX threads management (inputs reading)
|
||||||
|
#include <dirent.h> // POSIX directory browsing
|
||||||
|
|
||||||
|
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
||||||
|
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
||||||
|
#include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...)
|
||||||
|
#include <linux/joystick.h> // Linux: Joystick support library
|
||||||
|
|
||||||
|
#include <gbm.h> // Generic Buffer Management (native platform for EGL on DRM)
|
||||||
|
#include <xf86drm.h> // Direct Rendering Manager user-level library interface
|
||||||
|
#include <xf86drmMode.h> // Direct Rendering Manager mode setting (KMS) interface
|
||||||
|
|
||||||
|
#include "EGL/egl.h" // Native platform windowing system interface
|
||||||
|
#include "EGL/eglext.h" // EGL extensions
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
||||||
|
|
||||||
|
#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...)
|
||||||
|
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//...
|
|
||||||
|
typedef struct {
|
||||||
|
pthread_t threadId; // Event reading thread id
|
||||||
|
|
||||||
|
int fd; // File descriptor to the device it is assigned to
|
||||||
|
int eventNum; // Number of 'event<N>' device
|
||||||
|
Rectangle absRange; // Range of values for absolute pointing devices (touchscreens)
|
||||||
|
int touchSlot; // Hold the touch slot number of the currently being sent multitouch block
|
||||||
|
bool isMouse; // True if device supports relative X Y movements
|
||||||
|
bool isTouch; // True if device supports absolute X Y movements and has BTN_TOUCH
|
||||||
|
bool isMultitouch; // True if device supports multiple absolute movevents and has BTN_TOUCH
|
||||||
|
bool isKeyboard; // True if device has letter keycodes
|
||||||
|
bool isGamepad; // True if device has gamepad buttons
|
||||||
|
} InputEventWorker;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Display data
|
||||||
|
int fd; // File descriptor for /dev/dri/...
|
||||||
|
drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector
|
||||||
|
drmModeCrtc *crtc; // CRT Controller
|
||||||
|
int modeIndex; // Index of the used mode of connector->modes
|
||||||
|
struct gbm_device *gbmDevice; // GBM device
|
||||||
|
struct gbm_surface *gbmSurface; // GBM surface
|
||||||
|
struct gbm_bo *prevBO; // Previous GBM buffer object (during frame swapping)
|
||||||
|
uint32_t prevFB; // Previous GBM framebufer (during frame swapping)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Input data
|
||||||
|
InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>"
|
||||||
|
|
||||||
|
// Keyboard data
|
||||||
|
int defaultKeyboardMode; // Default keyboard mode
|
||||||
|
bool eventKeyboardMode; // Keyboard in event mode
|
||||||
|
int defaultFileFlags; // Default IO file flags
|
||||||
|
struct termios defaultSettings; // Default keyboard settings
|
||||||
|
int keyboardFd; // File descriptor for the evdev keyboard
|
||||||
|
|
||||||
|
// Mouse data
|
||||||
|
Vector2 eventWheelMove; // Registers the event mouse wheel variation
|
||||||
|
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
|
||||||
|
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
|
||||||
|
|
||||||
|
// Gamepad data
|
||||||
|
pthread_t gamepadThreadId; // Gamepad reading thread id
|
||||||
|
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
|
||||||
|
|
||||||
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
extern CoreData CORE; // Global CORE state context
|
extern CoreData CORE; // Global CORE state context
|
||||||
|
|
||||||
|
static PlatformData platform = { 0 }; // Platform specific data
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
|
@ -227,67 +307,67 @@ void CloseWindow(void)
|
||||||
timeEndPeriod(1); // Restore time period
|
timeEndPeriod(1); // Restore time period
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CORE.Window.prevFB)
|
if (platform.prevFB)
|
||||||
{
|
{
|
||||||
drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
|
drmModeRmFB(platform.fd, platform.prevFB);
|
||||||
CORE.Window.prevFB = 0;
|
platform.prevFB = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.prevBO)
|
if (platform.prevBO)
|
||||||
{
|
{
|
||||||
gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
|
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
|
||||||
CORE.Window.prevBO = NULL;
|
platform.prevBO = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.gbmSurface)
|
if (platform.gbmSurface)
|
||||||
{
|
{
|
||||||
gbm_surface_destroy(CORE.Window.gbmSurface);
|
gbm_surface_destroy(platform.gbmSurface);
|
||||||
CORE.Window.gbmSurface = NULL;
|
platform.gbmSurface = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.gbmDevice)
|
if (platform.gbmDevice)
|
||||||
{
|
{
|
||||||
gbm_device_destroy(CORE.Window.gbmDevice);
|
gbm_device_destroy(platform.gbmDevice);
|
||||||
CORE.Window.gbmDevice = NULL;
|
platform.gbmDevice = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.crtc)
|
if (platform.crtc)
|
||||||
{
|
{
|
||||||
if (CORE.Window.connector)
|
if (platform.connector)
|
||||||
{
|
{
|
||||||
drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, CORE.Window.crtc->buffer_id,
|
drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
|
||||||
CORE.Window.crtc->x, CORE.Window.crtc->y, &CORE.Window.connector->connector_id, 1, &CORE.Window.crtc->mode);
|
platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
|
||||||
drmModeFreeConnector(CORE.Window.connector);
|
drmModeFreeConnector(platform.connector);
|
||||||
CORE.Window.connector = NULL;
|
platform.connector = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeFreeCrtc(CORE.Window.crtc);
|
drmModeFreeCrtc(platform.crtc);
|
||||||
CORE.Window.crtc = NULL;
|
platform.crtc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.fd != -1)
|
if (platform.fd != -1)
|
||||||
{
|
{
|
||||||
close(CORE.Window.fd);
|
close(platform.fd);
|
||||||
CORE.Window.fd = -1;
|
platform.fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close surface, context and display
|
// Close surface, context and display
|
||||||
if (CORE.Window.device != EGL_NO_DISPLAY)
|
if (platform.device != EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
if (CORE.Window.surface != EGL_NO_SURFACE)
|
if (platform.surface != EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
eglDestroySurface(CORE.Window.device, CORE.Window.surface);
|
eglDestroySurface(platform.device, platform.surface);
|
||||||
CORE.Window.surface = EGL_NO_SURFACE;
|
platform.surface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Window.context != EGL_NO_CONTEXT)
|
if (platform.context != EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
eglDestroyContext(CORE.Window.device, CORE.Window.context);
|
eglDestroyContext(platform.device, platform.context);
|
||||||
CORE.Window.context = EGL_NO_CONTEXT;
|
platform.context = EGL_NO_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
eglTerminate(CORE.Window.device);
|
eglTerminate(platform.device);
|
||||||
CORE.Window.device = EGL_NO_DISPLAY;
|
platform.device = EGL_NO_DISPLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for mouse and gamepad threads to finish before closing
|
// Wait for mouse and gamepad threads to finish before closing
|
||||||
|
@ -297,21 +377,21 @@ void CloseWindow(void)
|
||||||
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
|
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
|
||||||
|
|
||||||
// Close the evdev keyboard
|
// Close the evdev keyboard
|
||||||
if (CORE.Input.Keyboard.fd != -1)
|
if (platform.keyboardFd != -1)
|
||||||
{
|
{
|
||||||
close(CORE.Input.Keyboard.fd);
|
close(platform.keyboardFd);
|
||||||
CORE.Input.Keyboard.fd = -1;
|
platform.keyboardFd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
|
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
||||||
{
|
{
|
||||||
if (CORE.Input.eventWorker[i].threadId)
|
if (platform.eventWorker[i].threadId)
|
||||||
{
|
{
|
||||||
pthread_join(CORE.Input.eventWorker[i].threadId, NULL);
|
pthread_join(platform.eventWorker[i].threadId, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CORE.Input.Gamepad.threadId) pthread_join(CORE.Input.Gamepad.threadId, NULL);
|
if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
RL_FREE(events);
|
RL_FREE(events);
|
||||||
|
@ -524,9 +604,9 @@ int GetMonitorRefreshRate(int monitor)
|
||||||
{
|
{
|
||||||
int refresh = 0;
|
int refresh = 0;
|
||||||
|
|
||||||
if ((CORE.Window.connector) && (CORE.Window.modeIndex >= 0))
|
if ((platform.connector) && (platform.modeIndex >= 0))
|
||||||
{
|
{
|
||||||
refresh = CORE.Window.connector->modes[CORE.Window.modeIndex].vrefresh;
|
refresh = platform.connector->modes[platform.modeIndex].vrefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
return refresh;
|
return refresh;
|
||||||
|
@ -659,7 +739,7 @@ const char *GetGamepadName(int gamepad)
|
||||||
|
|
||||||
if (CORE.Input.Gamepad.ready[gamepad])
|
if (CORE.Input.Gamepad.ready[gamepad])
|
||||||
{
|
{
|
||||||
ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name[gamepad]);
|
ioctl(platform.gamepadStreamFd[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name[gamepad]);
|
||||||
name = CORE.Input.Gamepad.name[gamepad];
|
name = CORE.Input.Gamepad.name[gamepad];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +750,7 @@ const char *GetGamepadName(int gamepad)
|
||||||
int GetGamepadAxisCount(int gamepad)
|
int GetGamepadAxisCount(int gamepad)
|
||||||
{
|
{
|
||||||
int axisCount = 0;
|
int axisCount = 0;
|
||||||
if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGAXES, &axisCount);
|
if (CORE.Input.Gamepad.ready[gamepad]) ioctl(platform.gamepadStreamFd[gamepad], JSIOCGAXES, &axisCount);
|
||||||
CORE.Input.Gamepad.axisCount = axisCount;
|
CORE.Input.Gamepad.axisCount = axisCount;
|
||||||
|
|
||||||
return CORE.Input.Gamepad.axisCount;
|
return CORE.Input.Gamepad.axisCount;
|
||||||
|
@ -756,31 +836,31 @@ Vector2 GetTouchPosition(int index)
|
||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
{
|
{
|
||||||
eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
|
eglSwapBuffers(platform.device, platform.surface);
|
||||||
|
|
||||||
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc) TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
|
if (!platform.gbmSurface || (-1 == platform.fd) || !platform.connector || !platform.crtc) TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
|
||||||
|
|
||||||
struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface);
|
struct gbm_bo *bo = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
||||||
if (!bo) TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
|
if (!bo) TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
|
||||||
|
|
||||||
uint32_t fb = 0;
|
uint32_t fb = 0;
|
||||||
int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay, CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb);
|
int result = drmModeAddFB(platform.fd, platform.connector->modes[platform.modeIndex].hdisplay, platform.connector->modes[platform.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb);
|
||||||
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
|
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
|
||||||
|
|
||||||
result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0, &CORE.Window.connector->connector_id, 1, &CORE.Window.connector->modes[CORE.Window.modeIndex]);
|
result = drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, fb, 0, 0, &platform.connector->connector_id, 1, &platform.connector->modes[platform.modeIndex]);
|
||||||
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
|
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
|
||||||
|
|
||||||
if (CORE.Window.prevFB)
|
if (platform.prevFB)
|
||||||
{
|
{
|
||||||
result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
|
result = drmModeRmFB(platform.fd, platform.prevFB);
|
||||||
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
|
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.prevFB = fb;
|
platform.prevFB = fb;
|
||||||
|
|
||||||
if (CORE.Window.prevBO) gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
|
if (platform.prevBO) gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
|
||||||
|
|
||||||
CORE.Window.prevBO = bo;
|
platform.prevBO = bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
|
@ -814,12 +894,12 @@ void PollInputEvents(void)
|
||||||
|
|
||||||
// Register previous mouse states
|
// Register previous mouse states
|
||||||
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
||||||
CORE.Input.Mouse.currentWheelMove = CORE.Input.Mouse.eventWheelMove;
|
CORE.Input.Mouse.currentWheelMove = platform.eventWheelMove;
|
||||||
CORE.Input.Mouse.eventWheelMove = (Vector2){ 0.0f, 0.0f };
|
platform.eventWheelMove = (Vector2){ 0.0f, 0.0f };
|
||||||
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++)
|
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
||||||
CORE.Input.Mouse.currentButtonState[i] = CORE.Input.Mouse.currentButtonStateEvdev[i];
|
CORE.Input.Mouse.currentButtonState[i] = platform.currentButtonStateEvdev[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register gamepads buttons events
|
// Register gamepads buttons events
|
||||||
|
@ -844,7 +924,7 @@ void PollInputEvents(void)
|
||||||
// NOTE: Keyboard reading could be done using input_event(s) or just read from stdin, both methods are used here.
|
// NOTE: Keyboard reading could be done using input_event(s) or just read from stdin, both methods are used here.
|
||||||
// stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console
|
// stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console
|
||||||
|
|
||||||
if (!CORE.Input.Keyboard.evtMode) ProcessKeyboard();
|
if (!platform.eventKeyboardMode) ProcessKeyboard();
|
||||||
|
|
||||||
// NOTE: Mouse input events polling is done asynchronously in another pthread - EventThread()
|
// NOTE: Mouse input events polling is done asynchronously in another pthread - EventThread()
|
||||||
// NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread()
|
// NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread()
|
||||||
|
@ -877,41 +957,41 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
CORE.Window.fullscreen = true;
|
CORE.Window.fullscreen = true;
|
||||||
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
CORE.Window.fd = -1;
|
platform.fd = -1;
|
||||||
CORE.Window.connector = NULL;
|
platform.connector = NULL;
|
||||||
CORE.Window.modeIndex = -1;
|
platform.modeIndex = -1;
|
||||||
CORE.Window.crtc = NULL;
|
platform.crtc = NULL;
|
||||||
CORE.Window.gbmDevice = NULL;
|
platform.gbmDevice = NULL;
|
||||||
CORE.Window.gbmSurface = NULL;
|
platform.gbmSurface = NULL;
|
||||||
CORE.Window.prevBO = NULL;
|
platform.prevBO = NULL;
|
||||||
CORE.Window.prevFB = 0;
|
platform.prevFB = 0;
|
||||||
|
|
||||||
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
||||||
CORE.Window.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
||||||
#else
|
#else
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
TRACELOG(LOG_INFO, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
||||||
CORE.Window.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
|
platform.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
|
||||||
|
|
||||||
if ((CORE.Window.fd == -1) || (drmModeGetResources(CORE.Window.fd) == NULL))
|
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
TRACELOG(LOG_INFO, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
||||||
CORE.Window.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
|
platform.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((CORE.Window.fd == -1) || (drmModeGetResources(CORE.Window.fd) == NULL))
|
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Failed to open graphic card1, trying card0");
|
TRACELOG(LOG_INFO, "DISPLAY: Failed to open graphic card1, trying card0");
|
||||||
CORE.Window.fd = open("/dev/dri/card0", O_RDWR); // VideoCore IV (Raspberry Pi 1-3)
|
platform.fd = open("/dev/dri/card0", O_RDWR); // VideoCore IV (Raspberry Pi 1-3)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CORE.Window.fd == -1)
|
if (platform.fd == -1)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeRes *res = drmModeGetResources(CORE.Window.fd);
|
drmModeRes *res = drmModeGetResources(platform.fd);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
|
||||||
|
@ -924,13 +1004,13 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: Connector index %i", i);
|
TRACELOG(LOG_TRACE, "DISPLAY: Connector index %i", i);
|
||||||
|
|
||||||
drmModeConnector *con = drmModeGetConnector(CORE.Window.fd, res->connectors[i]);
|
drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]);
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes);
|
TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes);
|
||||||
|
|
||||||
if ((con->connection == DRM_MODE_CONNECTED) && (con->encoder_id))
|
if ((con->connection == DRM_MODE_CONNECTED) && (con->encoder_id))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected");
|
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected");
|
||||||
CORE.Window.connector = con;
|
platform.connector = con;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -940,14 +1020,14 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CORE.Window.connector)
|
if (!platform.connector)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: No suitable DRM connector found");
|
TRACELOG(LOG_WARNING, "DISPLAY: No suitable DRM connector found");
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeEncoder *enc = drmModeGetEncoder(CORE.Window.fd, CORE.Window.connector->encoder_id);
|
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
|
||||||
if (!enc)
|
if (!enc)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
|
||||||
|
@ -955,8 +1035,8 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.crtc = drmModeGetCrtc(CORE.Window.fd, enc->crtc_id);
|
platform.crtc = drmModeGetCrtc(platform.fd, enc->crtc_id);
|
||||||
if (!CORE.Window.crtc)
|
if (!platform.crtc)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
|
||||||
drmModeFreeEncoder(enc);
|
drmModeFreeEncoder(enc);
|
||||||
|
@ -969,9 +1049,9 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: Selecting DRM connector mode for current used mode...");
|
TRACELOG(LOG_TRACE, "DISPLAY: Selecting DRM connector mode for current used mode...");
|
||||||
|
|
||||||
CORE.Window.modeIndex = FindMatchingConnectorMode(CORE.Window.connector, &CORE.Window.crtc->mode);
|
platform.modeIndex = FindMatchingConnectorMode(platform.connector, &platform.crtc->mode);
|
||||||
|
|
||||||
if (CORE.Window.modeIndex < 0)
|
if (platform.modeIndex < 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
|
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
|
||||||
drmModeFreeEncoder(enc);
|
drmModeFreeEncoder(enc);
|
||||||
|
@ -987,19 +1067,19 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
const int fps = (CORE.Time.target > 0)? (1.0/CORE.Time.target) : 60;
|
const int fps = (CORE.Time.target > 0)? (1.0/CORE.Time.target) : 60;
|
||||||
|
|
||||||
// Try to find an exact matching mode
|
// Try to find an exact matching mode
|
||||||
CORE.Window.modeIndex = FindExactConnectorMode(CORE.Window.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced);
|
platform.modeIndex = FindExactConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced);
|
||||||
|
|
||||||
// If nothing found, try to find a nearly matching mode
|
// If nothing found, try to find a nearly matching mode
|
||||||
if (CORE.Window.modeIndex < 0) CORE.Window.modeIndex = FindNearestConnectorMode(CORE.Window.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced);
|
if (platform.modeIndex < 0) platform.modeIndex = FindNearestConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced);
|
||||||
|
|
||||||
// If nothing found, try to find an exactly matching mode including interlaced
|
// If nothing found, try to find an exactly matching mode including interlaced
|
||||||
if (CORE.Window.modeIndex < 0) CORE.Window.modeIndex = FindExactConnectorMode(CORE.Window.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, true);
|
if (platform.modeIndex < 0) platform.modeIndex = FindExactConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, true);
|
||||||
|
|
||||||
// If nothing found, try to find a nearly matching mode including interlaced
|
// If nothing found, try to find a nearly matching mode including interlaced
|
||||||
if (CORE.Window.modeIndex < 0) CORE.Window.modeIndex = FindNearestConnectorMode(CORE.Window.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, true);
|
if (platform.modeIndex < 0) platform.modeIndex = FindNearestConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, true);
|
||||||
|
|
||||||
// If nothing found, there is no suitable mode
|
// If nothing found, there is no suitable mode
|
||||||
if (CORE.Window.modeIndex < 0)
|
if (platform.modeIndex < 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable DRM connector mode");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable DRM connector mode");
|
||||||
drmModeFreeEncoder(enc);
|
drmModeFreeEncoder(enc);
|
||||||
|
@ -1007,13 +1087,13 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.display.width = CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay;
|
CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay;
|
||||||
CORE.Window.display.height = CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay;
|
CORE.Window.display.height = platform.connector->modes[platform.modeIndex].vdisplay;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Selected DRM connector mode %s (%ux%u%c@%u)", CORE.Window.connector->modes[CORE.Window.modeIndex].name,
|
TRACELOG(LOG_INFO, "DISPLAY: Selected DRM connector mode %s (%ux%u%c@%u)", platform.connector->modes[platform.modeIndex].name,
|
||||||
CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay, CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay,
|
platform.connector->modes[platform.modeIndex].hdisplay, platform.connector->modes[platform.modeIndex].vdisplay,
|
||||||
(CORE.Window.connector->modes[CORE.Window.modeIndex].flags & DRM_MODE_FLAG_INTERLACE)? 'i' : 'p',
|
(platform.connector->modes[platform.modeIndex].flags & DRM_MODE_FLAG_INTERLACE)? 'i' : 'p',
|
||||||
CORE.Window.connector->modes[CORE.Window.modeIndex].vrefresh);
|
platform.connector->modes[platform.modeIndex].vrefresh);
|
||||||
|
|
||||||
// Use the width and height of the surface for render
|
// Use the width and height of the surface for render
|
||||||
CORE.Window.render.width = CORE.Window.screen.width;
|
CORE.Window.render.width = CORE.Window.screen.width;
|
||||||
|
@ -1025,16 +1105,16 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
|
||||||
CORE.Window.gbmDevice = gbm_create_device(CORE.Window.fd);
|
platform.gbmDevice = gbm_create_device(platform.fd);
|
||||||
if (!CORE.Window.gbmDevice)
|
if (!platform.gbmDevice)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.gbmSurface = gbm_surface_create(CORE.Window.gbmDevice, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay,
|
platform.gbmSurface = gbm_surface_create(platform.gbmDevice, platform.connector->modes[platform.modeIndex].hdisplay,
|
||||||
CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
platform.connector->modes[platform.modeIndex].vdisplay, GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
||||||
if (!CORE.Window.gbmSurface)
|
if (!platform.gbmSurface)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM surface");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM surface");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1073,22 +1153,22 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
EGLint numConfigs = 0;
|
EGLint numConfigs = 0;
|
||||||
|
|
||||||
// Get an EGL device connection
|
// Get an EGL device connection
|
||||||
CORE.Window.device = eglGetDisplay((EGLNativeDisplayType)CORE.Window.gbmDevice);
|
platform.device = eglGetDisplay((EGLNativeDisplayType)platform.gbmDevice);
|
||||||
if (CORE.Window.device == EGL_NO_DISPLAY)
|
if (platform.device == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the EGL device connection
|
// Initialize the EGL device connection
|
||||||
if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE)
|
if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE)
|
||||||
{
|
{
|
||||||
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglChooseConfig(CORE.Window.device, NULL, NULL, 0, &numConfigs))
|
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
||||||
return false;
|
return false;
|
||||||
|
@ -1104,7 +1184,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLint matchingNumConfigs = 0;
|
EGLint matchingNumConfigs = 0;
|
||||||
if (!eglChooseConfig(CORE.Window.device, framebufferAttribs, configs, numConfigs, &matchingNumConfigs))
|
if (!eglChooseConfig(platform.device, framebufferAttribs, configs, numConfigs, &matchingNumConfigs))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to choose EGL config: 0x%x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to choose EGL config: 0x%x", eglGetError());
|
||||||
free(configs);
|
free(configs);
|
||||||
|
@ -1118,7 +1198,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
for (EGLint i = 0; i < matchingNumConfigs; ++i)
|
for (EGLint i = 0; i < matchingNumConfigs; ++i)
|
||||||
{
|
{
|
||||||
EGLint id = 0;
|
EGLint id = 0;
|
||||||
if (!eglGetConfigAttrib(CORE.Window.device, configs[i], EGL_NATIVE_VISUAL_ID, &id))
|
if (!eglGetConfigAttrib(platform.device, configs[i], EGL_NATIVE_VISUAL_ID, &id))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config attribute: 0x%x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config attribute: 0x%x", eglGetError());
|
||||||
continue;
|
continue;
|
||||||
|
@ -1127,7 +1207,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (GBM_FORMAT_ARGB8888 == id)
|
if (GBM_FORMAT_ARGB8888 == id)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: Using EGL config: %d", i);
|
TRACELOG(LOG_TRACE, "DISPLAY: Using EGL config: %d", i);
|
||||||
CORE.Window.config = configs[i];
|
platform.config = configs[i];
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1145,8 +1225,8 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
eglBindAPI(EGL_OPENGL_ES_API);
|
eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
|
|
||||||
// Create an EGL rendering context
|
// Create an EGL rendering context
|
||||||
CORE.Window.context = eglCreateContext(CORE.Window.device, CORE.Window.config, EGL_NO_CONTEXT, contextAttribs);
|
platform.context = eglCreateContext(platform.device, platform.config, EGL_NO_CONTEXT, contextAttribs);
|
||||||
if (CORE.Window.context == EGL_NO_CONTEXT)
|
if (platform.context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1154,8 +1234,8 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
// Create an EGL window surface
|
// Create an EGL window surface
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, (EGLNativeWindowType)CORE.Window.gbmSurface, NULL);
|
platform.surface = eglCreateWindowSurface(platform.device, platform.config, (EGLNativeWindowType)platform.gbmSurface, NULL);
|
||||||
if (EGL_NO_SURFACE == CORE.Window.surface)
|
if (EGL_NO_SURFACE == platform.surface)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL window surface: 0x%04x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL window surface: 0x%04x", eglGetError());
|
||||||
return false;
|
return false;
|
||||||
|
@ -1169,9 +1249,9 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||||
|
|
||||||
// There must be at least one frame displayed before the buffers are swapped
|
// There must be at least one frame displayed before the buffers are swapped
|
||||||
//eglSwapInterval(CORE.Window.device, 1);
|
//eglSwapInterval(platform.device, 1);
|
||||||
|
|
||||||
if (eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context) == EGL_FALSE)
|
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");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1214,11 +1294,11 @@ static void InitKeyboard(void)
|
||||||
// Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE
|
// Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE
|
||||||
|
|
||||||
// Save terminal keyboard settings
|
// Save terminal keyboard settings
|
||||||
tcgetattr(STDIN_FILENO, &CORE.Input.Keyboard.defaultSettings);
|
tcgetattr(STDIN_FILENO, &platform.defaultSettings);
|
||||||
|
|
||||||
// Reconfigure terminal with new settings
|
// Reconfigure terminal with new settings
|
||||||
struct termios keyboardNewSettings = { 0 };
|
struct termios keyboardNewSettings = { 0 };
|
||||||
keyboardNewSettings = CORE.Input.Keyboard.defaultSettings;
|
keyboardNewSettings = platform.defaultSettings;
|
||||||
|
|
||||||
// New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing
|
// New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing
|
||||||
// NOTE: ISIG controls if ^C and ^Z generate break signals or not
|
// NOTE: ISIG controls if ^C and ^Z generate break signals or not
|
||||||
|
@ -1231,11 +1311,11 @@ static void InitKeyboard(void)
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings);
|
tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings);
|
||||||
|
|
||||||
// Save old keyboard mode to restore it at the end
|
// Save old keyboard mode to restore it at the end
|
||||||
CORE.Input.Keyboard.defaultFileFlags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags
|
platform.defaultFileFlags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags
|
||||||
fcntl(STDIN_FILENO, F_SETFL, CORE.Input.Keyboard.defaultFileFlags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified
|
fcntl(STDIN_FILENO, F_SETFL, platform.defaultFileFlags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified
|
||||||
|
|
||||||
// NOTE: If ioctl() returns -1, it means the call failed for some reason (error code set in errno)
|
// NOTE: If ioctl() returns -1, it means the call failed for some reason (error code set in errno)
|
||||||
int result = ioctl(STDIN_FILENO, KDGKBMODE, &CORE.Input.Keyboard.defaultMode);
|
int result = ioctl(STDIN_FILENO, KDGKBMODE, &platform.defaultKeyboardMode);
|
||||||
|
|
||||||
// In case of failure, it could mean a remote keyboard is used (SSH)
|
// In case of failure, it could mean a remote keyboard is used (SSH)
|
||||||
if (result < 0) TRACELOG(LOG_WARNING, "RPI: Failed to change keyboard mode, an SSH keyboard is probably used");
|
if (result < 0) TRACELOG(LOG_WARNING, "RPI: Failed to change keyboard mode, an SSH keyboard is probably used");
|
||||||
|
@ -1257,11 +1337,11 @@ static void InitKeyboard(void)
|
||||||
static void RestoreKeyboard(void)
|
static void RestoreKeyboard(void)
|
||||||
{
|
{
|
||||||
// Reset to default keyboard settings
|
// Reset to default keyboard settings
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &CORE.Input.Keyboard.defaultSettings);
|
tcsetattr(STDIN_FILENO, TCSANOW, &platform.defaultSettings);
|
||||||
|
|
||||||
// Reconfigure keyboard to default mode
|
// Reconfigure keyboard to default mode
|
||||||
fcntl(STDIN_FILENO, F_SETFL, CORE.Input.Keyboard.defaultFileFlags);
|
fcntl(STDIN_FILENO, F_SETFL, platform.defaultFileFlags);
|
||||||
ioctl(STDIN_FILENO, KDSKBMODE, CORE.Input.Keyboard.defaultMode);
|
ioctl(STDIN_FILENO, KDSKBMODE, platform.defaultKeyboardMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
||||||
|
@ -1389,7 +1469,7 @@ static void InitEvdevInput(void)
|
||||||
struct dirent *entity = NULL;
|
struct dirent *entity = NULL;
|
||||||
|
|
||||||
// Initialise keyboard file descriptor
|
// Initialise keyboard file descriptor
|
||||||
CORE.Input.Keyboard.fd = -1;
|
platform.keyboardFd = -1;
|
||||||
|
|
||||||
// Reset variables
|
// Reset variables
|
||||||
for (int i = 0; i < MAX_TOUCH_POINTS; ++i)
|
for (int i = 0; i < MAX_TOUCH_POINTS; ++i)
|
||||||
|
@ -1451,9 +1531,9 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
// Open the device and allocate worker
|
// Open the device and allocate worker
|
||||||
//-------------------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------------------
|
||||||
// Find a free spot in the workers array
|
// Find a free spot in the workers array
|
||||||
for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
|
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
||||||
{
|
{
|
||||||
if (CORE.Input.eventWorker[i].threadId == 0)
|
if (platform.eventWorker[i].threadId == 0)
|
||||||
{
|
{
|
||||||
freeWorkerId = i;
|
freeWorkerId = i;
|
||||||
break;
|
break;
|
||||||
|
@ -1463,7 +1543,7 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
// Select the free worker from array
|
// Select the free worker from array
|
||||||
if (freeWorkerId >= 0)
|
if (freeWorkerId >= 0)
|
||||||
{
|
{
|
||||||
worker = &(CORE.Input.eventWorker[freeWorkerId]); // Grab a pointer to the worker
|
worker = &(platform.eventWorker[freeWorkerId]); // Grab a pointer to the worker
|
||||||
memset(worker, 0, sizeof(InputEventWorker)); // Clear the worker
|
memset(worker, 0, sizeof(InputEventWorker)); // Clear the worker
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1574,13 +1654,13 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
|
|
||||||
// Decide what to do with the device
|
// Decide what to do with the device
|
||||||
//-------------------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------------------
|
||||||
if (worker->isKeyboard && (CORE.Input.Keyboard.fd == -1))
|
if (worker->isKeyboard && (platform.keyboardFd == -1))
|
||||||
{
|
{
|
||||||
// Use the first keyboard encountered. This assumes that a device that says it's a keyboard is just a
|
// Use the first keyboard encountered. This assumes that a device that says it's a keyboard is just a
|
||||||
// keyboard. The keyboard is polled synchronously, whereas other input devices are polled in separate
|
// keyboard. The keyboard is polled synchronously, whereas other input devices are polled in separate
|
||||||
// threads so that they don't drop events when the frame rate is slow.
|
// threads so that they don't drop events when the frame rate is slow.
|
||||||
TRACELOG(LOG_INFO, "RPI: Opening keyboard device: %s", device);
|
TRACELOG(LOG_INFO, "RPI: Opening keyboard device: %s", device);
|
||||||
CORE.Input.Keyboard.fd = worker->fd;
|
platform.keyboardFd = worker->fd;
|
||||||
}
|
}
|
||||||
else if (worker->isTouch || worker->isMouse)
|
else if (worker->isTouch || worker->isMouse)
|
||||||
{
|
{
|
||||||
|
@ -1604,21 +1684,21 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
// Find touchscreen with the highest index
|
// Find touchscreen with the highest index
|
||||||
int maxTouchNumber = -1;
|
int maxTouchNumber = -1;
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
|
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
||||||
{
|
{
|
||||||
if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum > maxTouchNumber)) maxTouchNumber = CORE.Input.eventWorker[i].eventNum;
|
if (platform.eventWorker[i].isTouch && (platform.eventWorker[i].eventNum > maxTouchNumber)) maxTouchNumber = platform.eventWorker[i].eventNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find touchscreens with lower indexes
|
// Find touchscreens with lower indexes
|
||||||
for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
|
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
||||||
{
|
{
|
||||||
if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum < maxTouchNumber))
|
if (platform.eventWorker[i].isTouch && (platform.eventWorker[i].eventNum < maxTouchNumber))
|
||||||
{
|
{
|
||||||
if (CORE.Input.eventWorker[i].threadId != 0)
|
if (platform.eventWorker[i].threadId != 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "RPI: Found duplicate touchscreen, killing touchscreen on event: %d", i);
|
TRACELOG(LOG_WARNING, "RPI: Found duplicate touchscreen, killing touchscreen on event: %d", i);
|
||||||
pthread_cancel(CORE.Input.eventWorker[i].threadId);
|
pthread_cancel(platform.eventWorker[i].threadId);
|
||||||
close(CORE.Input.eventWorker[i].fd);
|
close(platform.eventWorker[i].fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1652,7 +1732,7 @@ static void PollKeyboardEvents(void)
|
||||||
243, 244, 245, 246, 247, 248, 0, 0, 0, 0, 0, 0, 0
|
243, 244, 245, 246, 247, 248, 0, 0, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
int fd = CORE.Input.Keyboard.fd;
|
int fd = platform.keyboardFd;
|
||||||
if (fd == -1) return;
|
if (fd == -1) return;
|
||||||
|
|
||||||
struct input_event event = { 0 };
|
struct input_event event = { 0 };
|
||||||
|
@ -1666,7 +1746,7 @@ static void PollKeyboardEvents(void)
|
||||||
{
|
{
|
||||||
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
||||||
// Change keyboard mode to events
|
// Change keyboard mode to events
|
||||||
CORE.Input.Keyboard.evtMode = true;
|
platform.eventKeyboardMode = true;
|
||||||
#endif
|
#endif
|
||||||
// Keyboard button parsing
|
// Keyboard button parsing
|
||||||
if ((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
|
if ((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
|
||||||
|
@ -1739,7 +1819,7 @@ static void *EventThread(void *arg)
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == REL_WHEEL) CORE.Input.Mouse.eventWheelMove.y += event.value;
|
if (event.code == REL_WHEEL) platform.eventWheelMove.y += event.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Absolute movement parsing
|
// Absolute movement parsing
|
||||||
|
@ -1790,11 +1870,11 @@ static void *EventThread(void *arg)
|
||||||
// Touchscreen tap
|
// Touchscreen tap
|
||||||
if (event.code == ABS_PRESSURE)
|
if (event.code == ABS_PRESSURE)
|
||||||
{
|
{
|
||||||
int previousMouseLeftButtonState = CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT];
|
int previousMouseLeftButtonState = platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT];
|
||||||
|
|
||||||
if (!event.value && previousMouseLeftButtonState)
|
if (!event.value && previousMouseLeftButtonState)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0;
|
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0;
|
||||||
|
|
||||||
touchAction = 0; // TOUCH_ACTION_UP
|
touchAction = 0; // TOUCH_ACTION_UP
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
|
@ -1802,7 +1882,7 @@ static void *EventThread(void *arg)
|
||||||
|
|
||||||
if (event.value && !previousMouseLeftButtonState)
|
if (event.value && !previousMouseLeftButtonState)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1;
|
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1;
|
||||||
|
|
||||||
touchAction = 1; // TOUCH_ACTION_DOWN
|
touchAction = 1; // TOUCH_ACTION_DOWN
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
|
@ -1817,19 +1897,19 @@ static void *EventThread(void *arg)
|
||||||
// Mouse button parsing
|
// Mouse button parsing
|
||||||
if ((event.code == BTN_TOUCH) || (event.code == BTN_LEFT))
|
if ((event.code == BTN_TOUCH) || (event.code == BTN_LEFT))
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = event.value;
|
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = event.value;
|
||||||
|
|
||||||
if (event.value > 0) touchAction = 1; // TOUCH_ACTION_DOWN
|
if (event.value > 0) touchAction = 1; // TOUCH_ACTION_DOWN
|
||||||
else touchAction = 0; // TOUCH_ACTION_UP
|
else touchAction = 0; // TOUCH_ACTION_UP
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == BTN_RIGHT) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value;
|
if (event.code == BTN_RIGHT) platform.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value;
|
||||||
if (event.code == BTN_MIDDLE) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_MIDDLE] = event.value;
|
if (event.code == BTN_MIDDLE) platform.currentButtonStateEvdev[MOUSE_BUTTON_MIDDLE] = event.value;
|
||||||
if (event.code == BTN_SIDE) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_SIDE] = event.value;
|
if (event.code == BTN_SIDE) platform.currentButtonStateEvdev[MOUSE_BUTTON_SIDE] = event.value;
|
||||||
if (event.code == BTN_EXTRA) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_EXTRA] = event.value;
|
if (event.code == BTN_EXTRA) platform.currentButtonStateEvdev[MOUSE_BUTTON_EXTRA] = event.value;
|
||||||
if (event.code == BTN_FORWARD) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_FORWARD] = event.value;
|
if (event.code == BTN_FORWARD) platform.currentButtonStateEvdev[MOUSE_BUTTON_FORWARD] = event.value;
|
||||||
if (event.code == BTN_BACK) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_BACK] = event.value;
|
if (event.code == BTN_BACK) platform.currentButtonStateEvdev[MOUSE_BUTTON_BACK] = event.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Screen confinement
|
// Screen confinement
|
||||||
|
@ -1885,7 +1965,7 @@ static void InitGamepad(void)
|
||||||
{
|
{
|
||||||
sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i);
|
sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i);
|
||||||
|
|
||||||
if ((CORE.Input.Gamepad.streamId[i] = open(gamepadDev, O_RDONLY | O_NONBLOCK)) < 0)
|
if ((platform.gamepadStreamFd[i] = open(gamepadDev, O_RDONLY | O_NONBLOCK)) < 0)
|
||||||
{
|
{
|
||||||
// NOTE: Only show message for first gamepad
|
// NOTE: Only show message for first gamepad
|
||||||
if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available");
|
if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available");
|
||||||
|
@ -1897,7 +1977,7 @@ static void InitGamepad(void)
|
||||||
// NOTE: Only create one thread
|
// NOTE: Only create one thread
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
int error = pthread_create(&CORE.Input.Gamepad.threadId, NULL, &GamepadThread, NULL);
|
int error = pthread_create(&platform.gamepadThreadId, NULL, &GamepadThread, NULL);
|
||||||
|
|
||||||
if (error != 0) TRACELOG(LOG_WARNING, "RPI: Failed to create gamepad input event thread");
|
if (error != 0) TRACELOG(LOG_WARNING, "RPI: Failed to create gamepad input event thread");
|
||||||
else TRACELOG(LOG_INFO, "RPI: Gamepad device initialized successfully");
|
else TRACELOG(LOG_INFO, "RPI: Gamepad device initialized successfully");
|
||||||
|
@ -1927,7 +2007,7 @@ static void *GamepadThread(void *arg)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
if (read(CORE.Input.Gamepad.streamId[i], &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
|
if (read(platform.gamepadStreamFd[i], &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
|
||||||
{
|
{
|
||||||
gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events
|
gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events
|
||||||
|
|
||||||
|
@ -1977,7 +2057,7 @@ static int FindMatchingConnectorMode(const drmModeConnector *connector, const dr
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, connector->modes[i].hdisplay, connector->modes[i].vdisplay,
|
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, connector->modes[i].hdisplay, connector->modes[i].vdisplay,
|
||||||
connector->modes[i].vrefresh, (connector->modes[i].flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
connector->modes[i].vrefresh, (connector->modes[i].flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
||||||
|
|
||||||
if (0 == BINCMP(&CORE.Window.crtc->mode, &CORE.Window.connector->modes[i])) return i;
|
if (0 == BINCMP(&platform.crtc->mode, &platform.connector->modes[i])) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1992,9 +2072,9 @@ static int FindExactConnectorMode(const drmModeConnector *connector, uint width,
|
||||||
|
|
||||||
if (NULL == connector) return -1;
|
if (NULL == connector) return -1;
|
||||||
|
|
||||||
for (int i = 0; i < CORE.Window.connector->count_modes; i++)
|
for (int i = 0; i < platform.connector->count_modes; i++)
|
||||||
{
|
{
|
||||||
const drmModeModeInfo *const mode = &CORE.Window.connector->modes[i];
|
const drmModeModeInfo *const mode = &platform.connector->modes[i];
|
||||||
|
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
||||||
|
|
||||||
|
@ -2015,9 +2095,9 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
||||||
if (NULL == connector) return -1;
|
if (NULL == connector) return -1;
|
||||||
|
|
||||||
int nearestIndex = -1;
|
int nearestIndex = -1;
|
||||||
for (int i = 0; i < CORE.Window.connector->count_modes; i++)
|
for (int i = 0; i < platform.connector->count_modes; i++)
|
||||||
{
|
{
|
||||||
const drmModeModeInfo *const mode = &CORE.Window.connector->modes[i];
|
const drmModeModeInfo *const mode = &platform.connector->modes[i];
|
||||||
|
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh,
|
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh,
|
||||||
(mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
(mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
||||||
|
@ -2044,9 +2124,9 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
||||||
const int heightDiff = abs(mode->vdisplay - height);
|
const int heightDiff = abs(mode->vdisplay - height);
|
||||||
const int fpsDiff = abs(mode->vrefresh - fps);
|
const int fpsDiff = abs(mode->vrefresh - fps);
|
||||||
|
|
||||||
const int nearestWidthDiff = abs(CORE.Window.connector->modes[nearestIndex].hdisplay - width);
|
const int nearestWidthDiff = abs(platform.connector->modes[nearestIndex].hdisplay - width);
|
||||||
const int nearestHeightDiff = abs(CORE.Window.connector->modes[nearestIndex].vdisplay - height);
|
const int nearestHeightDiff = abs(platform.connector->modes[nearestIndex].vdisplay - height);
|
||||||
const int nearestFpsDiff = abs(CORE.Window.connector->modes[nearestIndex].vrefresh - fps);
|
const int nearestFpsDiff = abs(platform.connector->modes[nearestIndex].vrefresh - fps);
|
||||||
|
|
||||||
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) {
|
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) {
|
||||||
nearestIndex = i;
|
nearestIndex = i;
|
||||||
|
|
|
@ -47,23 +47,42 @@
|
||||||
|
|
||||||
#include "rcore.h"
|
#include "rcore.h"
|
||||||
|
|
||||||
#define GLFW_INCLUDE_ES2 // GLFW3: Enable OpenGL ES 2.0 (translated to WebGL)
|
#define GLFW_INCLUDE_ES2 // GLFW3: Enable OpenGL ES 2.0 (translated to WebGL)
|
||||||
// #define GLFW_INCLUDE_ES3 // GLFW3: Enable OpenGL ES 3.0 (transalted to WebGL2?)
|
// #define GLFW_INCLUDE_ES3 // GLFW3: Enable OpenGL ES 3.0 (transalted to WebGL2?)
|
||||||
#include "GLFW/glfw3.h" // GLFW3: Windows, OpenGL context and Input management
|
#include "GLFW/glfw3.h" // GLFW3: Windows, OpenGL context and Input management
|
||||||
|
|
||||||
|
#include <emscripten/emscripten.h> // Emscripten functionality for C
|
||||||
|
#include <emscripten/html5.h> // Emscripten HTML5 library
|
||||||
|
|
||||||
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
||||||
|
|
||||||
#include <emscripten/emscripten.h> // Emscripten functionality for C
|
//----------------------------------------------------------------------------------
|
||||||
#include <emscripten/html5.h> // Emscripten HTML5 library
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// TODO: HACK: Added flag if not provided by GLFW when using external library
|
||||||
|
// Latest GLFW release (GLFW 3.3.8) does not implement this flag, it was added for 3.4.0-dev
|
||||||
|
#if !defined(GLFW_MOUSE_PASSTHROUGH)
|
||||||
|
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (_POSIX_C_SOURCE < 199309L)
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//...
|
typedef struct {
|
||||||
|
GLFWwindow *handle; // GLFW window handle (graphic device)
|
||||||
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
extern CoreData CORE; // Global CORE state context
|
extern CoreData CORE; // Global CORE state context
|
||||||
|
|
||||||
|
static PlatformData platform = { 0 }; // Platform specific data
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
|
@ -263,7 +282,7 @@ void CloseWindow(void)
|
||||||
|
|
||||||
rlglClose(); // De-init rlgl
|
rlglClose(); // De-init rlgl
|
||||||
|
|
||||||
glfwDestroyWindow(CORE.Window.handle);
|
glfwDestroyWindow(platform.handle);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
||||||
|
@ -481,7 +500,7 @@ void SetWindowMaxSize(int width, int height)
|
||||||
// Set window dimensions
|
// Set window dimensions
|
||||||
void SetWindowSize(int width, int height)
|
void SetWindowSize(int width, int height)
|
||||||
{
|
{
|
||||||
glfwSetWindowSize(CORE.Window.handle, width, height);
|
glfwSetWindowSize(platform.handle, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window opacity, value opacity is between 0.0 and 1.0
|
// Set window opacity, value opacity is between 0.0 and 1.0
|
||||||
|
@ -759,7 +778,7 @@ void SetMousePosition(int x, int y)
|
||||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
||||||
// NOTE: emscripten not implemented
|
// NOTE: emscripten not implemented
|
||||||
glfwSetCursorPos(CORE.Window.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
// Get mouse wheel movement Y
|
||||||
|
@ -806,7 +825,7 @@ Vector2 GetTouchPosition(int index)
|
||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
{
|
{
|
||||||
glfwSwapBuffers(CORE.Window.handle);
|
glfwSwapBuffers(platform.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
|
@ -1110,24 +1129,24 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
|
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
|
||||||
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||||
|
|
||||||
CORE.Window.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", glfwGetPrimaryMonitor(), NULL);
|
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", glfwGetPrimaryMonitor(), NULL);
|
||||||
|
|
||||||
// NOTE: Full-screen change, not working properly...
|
// NOTE: Full-screen change, not working properly...
|
||||||
// glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
// glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No-fullscreen window creation
|
// No-fullscreen window creation
|
||||||
CORE.Window.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
platform.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
||||||
|
|
||||||
if (CORE.Window.handle)
|
if (platform.handle)
|
||||||
{
|
{
|
||||||
CORE.Window.render.width = CORE.Window.screen.width;
|
CORE.Window.render.width = CORE.Window.screen.width;
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CORE.Window.handle)
|
if (!platform.handle)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||||
|
@ -1138,20 +1157,20 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
emscripten_set_window_title((CORE.Window.title != 0)? CORE.Window.title : " ");
|
emscripten_set_window_title((CORE.Window.title != 0)? CORE.Window.title : " ");
|
||||||
|
|
||||||
// Set window callback events
|
// Set window callback events
|
||||||
glfwSetWindowSizeCallback(CORE.Window.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
|
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
|
||||||
glfwSetWindowIconifyCallback(CORE.Window.handle, WindowIconifyCallback);
|
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
|
||||||
glfwSetWindowFocusCallback(CORE.Window.handle, WindowFocusCallback);
|
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
|
||||||
glfwSetDropCallback(CORE.Window.handle, WindowDropCallback);
|
glfwSetDropCallback(platform.handle, WindowDropCallback);
|
||||||
|
|
||||||
// Set input callback events
|
// Set input callback events
|
||||||
glfwSetKeyCallback(CORE.Window.handle, KeyCallback);
|
glfwSetKeyCallback(platform.handle, KeyCallback);
|
||||||
glfwSetCharCallback(CORE.Window.handle, CharCallback);
|
glfwSetCharCallback(platform.handle, CharCallback);
|
||||||
glfwSetMouseButtonCallback(CORE.Window.handle, MouseButtonCallback);
|
glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback);
|
||||||
glfwSetCursorPosCallback(CORE.Window.handle, MouseCursorPosCallback); // Track mouse position changes
|
glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes
|
||||||
glfwSetScrollCallback(CORE.Window.handle, MouseScrollCallback);
|
glfwSetScrollCallback(platform.handle, MouseScrollCallback);
|
||||||
glfwSetCursorEnterCallback(CORE.Window.handle, CursorEnterCallback);
|
glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);
|
||||||
|
|
||||||
glfwMakeContextCurrent(CORE.Window.handle);
|
glfwMakeContextCurrent(platform.handle);
|
||||||
|
|
||||||
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
||||||
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
|
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
|
||||||
|
@ -1293,7 +1312,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the exit key to set close window
|
// Check the exit key to set close window
|
||||||
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(CORE.Window.handle, GLFW_TRUE);
|
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(platform.handle, GLFW_TRUE);
|
||||||
|
|
||||||
#if defined(SUPPORT_SCREEN_CAPTURE)
|
#if defined(SUPPORT_SCREEN_CAPTURE)
|
||||||
if ((key == GLFW_KEY_F12) && (action == GLFW_PRESS))
|
if ((key == GLFW_KEY_F12) && (action == GLFW_PRESS))
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <android/asset_manager.h> // Required for: AAssetManager
|
#include <android/asset_manager.h> // Required for: AAssetManager
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_TRACELOG)
|
#if defined(SUPPORT_TRACELOG) && !defined(TRACELOG)
|
||||||
#define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
|
#define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
|
||||||
|
|
||||||
#if defined(SUPPORT_TRACELOG_DEBUG)
|
#if defined(SUPPORT_TRACELOG_DEBUG)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue