aboutsummaryrefslogtreecommitdiff
path: root/src/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core.c')
-rw-r--r--src/core.c469
1 files changed, 363 insertions, 106 deletions
diff --git a/src/core.c b/src/core.c
index 5172a710..1cafac28 100644
--- a/src/core.c
+++ b/src/core.c
@@ -3,17 +3,19 @@
* raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms
*
* PLATFORMS SUPPORTED:
-* - Windows (win32/Win64)
-* - Linux (tested on Ubuntu)
-* - OSX (Mac)
-* - Android (ARM or ARM64)
-* - Raspberry Pi (Raspbian)
-* - HTML5 (Chrome, Firefox)
+* - PLATFORM_DESKTOP: Windows (Win32, Win64)
+* - PLATFORM_DESKTOP: Linux (X11 desktop mode)
+* - PLATFORM_DESKTOP: FreeBSD (X11 desktop)
+* - PLATFORM_DESKTOP: OSX/macOS
+* - PLATFORM_ANDROID: Android 4.0 (ARM, ARM64)
+* - PLATFORM_RPI: Raspberry Pi 0,1,2,3 (Raspbian)
+* - PLATFORM_WEB: HTML5 with asm.js (Chrome, Firefox)
+* - PLATFORM_UWP: Windows 10 App, Windows Phone, Xbox One
*
* CONFIGURATION:
*
* #define PLATFORM_DESKTOP
-* Windowing and input system configured for desktop platforms: Windows, Linux, OSX (managed by GLFW3 library)
+* Windowing and input system configured for desktop platforms: Windows, Linux, OSX, FreeBSD
* NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for mirror rendering - View [rlgl] module to enable it
*
* #define PLATFORM_ANDROID
@@ -21,13 +23,17 @@
* NOTE: OpenGL ES 2.0 is required and graphic device is managed by EGL
*
* #define PLATFORM_RPI
-* Windowing and input system configured for Raspberry Pi (tested on Raspbian), graphic device is managed by EGL
-* and inputs are processed is raw mode, reading from /dev/input/
+* Windowing and input system configured for Raspberry Pi i native mode (no X.org required, tested on Raspbian),
+* 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 PLATFORM_UWP
+* Universal Windows Platform support, using OpenGL ES 2.0 through ANGLE on multiple Windows platforms,
+* including Windows 10 App, Windows Phone and Xbox One platforms.
+*
* #define SUPPORT_DEFAULT_FONT (default)
* 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)
@@ -48,15 +54,15 @@
* Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
*
* DEPENDENCIES:
-* GLFW3 - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX)
-* raymath - 3D math functionality (Vector3, Matrix, Quaternion)
+* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD)
+* raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion)
* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person)
* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs)
*
*
* LICENSE: zlib/libpng
*
-* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
+* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
*
* 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.
@@ -87,6 +93,11 @@
#include "raylib.h"
+#if (defined(__linux__) || defined(PLATFORM_WEB)) && _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
+
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
#include "utils.h" // Required for: fopen() Android mapping
@@ -109,10 +120,6 @@
#include "external/rgif.h" // Support GIF recording
#endif
-#if defined(__linux__) || defined(PLATFORM_WEB)
- #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
-#endif
-
#include <stdio.h> // Standard input / output lib
#include <stdlib.h> // Required for: malloc(), free(), rand(), atexit()
#include <stdint.h> // Required for: typedef unsigned long long int uint64_t, used by hi-res timer
@@ -121,7 +128,7 @@
#include <string.h> // Required for: strrchr(), strcmp()
//#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
-#ifdef _WIN32
+#if defined(_WIN32)
#include <direct.h> // Required for: _getch(), _chdir()
#define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir()
#define CHDIR _chdir
@@ -147,12 +154,11 @@
#include <GLFW/glfw3native.h> // which are required for hiding mouse
#endif
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
- //#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
-
+
#if !defined(SUPPORT_BUSY_WAIT_LOOP) && defined(_WIN32)
// NOTE: Those functions require linking with winmm library
- __stdcall unsigned int timeBeginPeriod(unsigned int uPeriod);
- __stdcall unsigned int timeEndPeriod(unsigned int uPeriod);
+ unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
+ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif
#endif
@@ -183,6 +189,12 @@
#include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
#endif
+#if defined(PLATFORM_UWP)
+ #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions
+ #include "EGL/eglext.h" // Khronos EGL library - Extensions
+ #include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
+#endif
+
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
@@ -222,16 +234,17 @@
//----------------------------------------------------------------------------------
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
static GLFWwindow *window; // Native window (graphic device)
-static bool windowMinimized = false;
#endif
+static bool windowReady = false; // Check if window has been initialized successfully
+static bool windowMinimized = false; // Check if window has been minimized
+
#if defined(PLATFORM_ANDROID)
static struct android_app *app; // Android activity
static struct android_poll_source *source; // Android events polling source
static int ident, events; // Android ALooper_pollAll() variables
static const char *internalDataPath; // Android internal data path to write data (/data/data/<package>/files)
-static bool windowReady = false; // Used to detect display initialization
static bool appEnabled = true; // Used to detec if app is active
static bool contextRebindRequired = false; // Used to know context rebind required
#endif
@@ -260,7 +273,7 @@ static pthread_t gamepadThreadId; // Gamepad reading thread id
static char gamepadName[64]; // Gamepad name holder
#endif
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
static EGLDisplay display; // Native display device (physical screen connection)
static EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
static EGLContext context; // Graphic context, mode in which drawing can be done
@@ -269,6 +282,10 @@ static uint64_t baseTime; // Base time measure for hi-res timer
static bool windowShouldClose = false; // Flag to set window for closing
#endif
+#if defined(PLATFORM_UWP)
+static EGLNativeWindowType uwpWindow;
+#endif
+
// Display size-related data
static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...)
static int screenWidth, screenHeight; // Screen width and height (used render area)
@@ -278,10 +295,10 @@ static int renderOffsetY = 0; // Offset Y from render area (must b
static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP)
static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size)
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
-static const char *windowTitle; // Window text title...
-static bool cursorOnScreen = false; // Tracks if cursor is inside client area
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
+static const char *windowTitle = NULL; // Window text title...
static bool cursorHidden = false; // Track if cursor is hidden
+static bool cursorOnScreen = false; // Tracks if cursor is inside client area
static int screenshotCounter = 0; // Screenshots counter
// Register mouse states
@@ -326,7 +343,7 @@ static double updateTime, drawTime; // Time measures for update and draw
static double frameTime = 0.0; // Time measure for one frame
static double targetTime = 0.0; // Desired time for one frame, if 0 not applied
-static char configFlags = 0; // Configuration flags (bit based)
+static unsigned char configFlags = 0; // Configuration flags (bit based)
static bool showLogo = false; // Track if showing logo at init is enabled
#if defined(SUPPORT_GIF_RECORDING)
@@ -345,10 +362,9 @@ extern void UnloadDefaultFont(void); // [Module: text] Unloads default fo
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
-static void InitGraphicsDevice(int width, int height); // Initialize graphics device
+static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
static void SetupFramebufferSize(int displayWidth, int displayHeight);
static void InitTimer(void); // Initialize timer
-static double GetTime(void); // Returns time since InitTimer() was run
static void Wait(float ms); // Wait for some milliseconds (stop program execution)
static bool GetKeyStatus(int key); // Returns if a key has been pressed
static bool GetMouseButtonStatus(int button); // Returns if a mouse button has been pressed
@@ -398,6 +414,10 @@ static void InitGamepad(void); // Init raw gamepad inpu
static void *GamepadThread(void *arg); // Mouse reading thread
#endif
+#if defined(PLATFORM_UWP)
+// Define functions required to manage inputs
+#endif
+
#if defined(_WIN32)
// NOTE: We include Sleep() function signature here to avoid windows.h inclusion
void __stdcall Sleep(unsigned long msTimeout); // Required for Wait()
@@ -406,17 +426,27 @@ static void *GamepadThread(void *arg); // Mouse reading thread
//----------------------------------------------------------------------------------
// Module Functions Definition - Window and OpenGL Context Functions
//----------------------------------------------------------------------------------
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
// Initialize window and OpenGL context
-void InitWindow(int width, int height, const char *title)
+// NOTE: data parameter could be used to pass any kind of required data to the initialization
+void InitWindow(int width, int height, void *data)
{
- TraceLog(LOG_INFO, "Initializing raylib (v1.8.0)");
+ TraceLog(LOG_INFO, "Initializing raylib (v1.9.3-dev)");
+
+#if defined(PLATFORM_DESKTOP)
+ windowTitle = (char *)data;
+#endif
- // Store window title (could be useful...)
- windowTitle = title;
+#if defined(PLATFORM_UWP)
+ uwpWindow = (EGLNativeWindowType)data;
+#endif
// Init graphics device (display device and OpenGL context)
- InitGraphicsDevice(width, height);
+ // NOTE: returns true if window and graphic device has been initialized successfully
+ windowReady = InitGraphicsDevice(width, height);
+
+ // Init hi-res timer
+ InitTimer();
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
@@ -424,9 +454,6 @@ void InitWindow(int width, int height, const char *title)
LoadDefaultFont();
#endif
- // Init hi-res timer
- InitTimer();
-
#if defined(PLATFORM_RPI)
// Init raw input system
InitMouse(); // Mouse init
@@ -470,15 +497,17 @@ void InitWindow(int width, int height, const char *title)
#endif
#if defined(PLATFORM_ANDROID)
-// Initialize Android activity
-void InitWindow(int width, int height, void *state)
+// Initialize window and OpenGL context (and Android activity)
+// NOTE: data parameter could be used to pass any kind of required data to the initialization
+void InitWindow(int width, int height, void *data)
{
- TraceLog(LOG_INFO, "Initializing raylib (v1.8.0)");
+ TraceLog(LOG_INFO, "Initializing raylib (v1.9.3-dev)");
screenWidth = width;
screenHeight = height;
- app = (struct android_app *)state;
+ // Input data is android app pointer
+ app = (struct android_app *)data;
internalDataPath = app->activity->internalDataPath;
// Set desired windows flags before initializing anything
@@ -507,7 +536,6 @@ void InitWindow(int width, int height, void *state)
//AConfiguration_getScreenSize(app->config);
//AConfiguration_getScreenLong(app->config);
- //state->userData = &engine;
app->onAppCmd = AndroidCommandCallback;
app->onInputEvent = AndroidInputCallback;
@@ -557,7 +585,7 @@ void CloseWindow(void)
timeEndPeriod(1); // Restore time period
#endif
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
// Close surface, context and display
if (display != EGL_NO_DISPLAY)
{
@@ -595,25 +623,36 @@ void CloseWindow(void)
TraceLog(LOG_INFO, "Window closed successfully");
}
+// Check if window has been initialized successfully
+bool IsWindowReady(void)
+{
+ return windowReady;
+}
+
// Check if KEY_ESCAPE pressed or Close icon pressed
bool WindowShouldClose(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
- // While window minimized, stop loop execution
- while (windowMinimized) glfwWaitEvents();
+ if (windowReady)
+ {
+ // While window minimized, stop loop execution
+ while (windowMinimized) glfwWaitEvents();
- return (glfwWindowShouldClose(window));
+ return (glfwWindowShouldClose(window));
+ }
+ else return true;
#endif
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
- return windowShouldClose;
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
+ if (windowReady) return windowShouldClose;
+ else return true;
#endif
}
// Check if window has been minimized (or lost focus)
bool IsWindowMinimized(void)
{
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
return windowMinimized;
#else
return false;
@@ -680,7 +719,7 @@ void SetWindowMonitor(int monitor)
if ((monitor >= 0) && (monitor < monitorCount))
{
- glfwSetWindowMonitor(window, monitors[monitor], 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
+ //glfwSetWindowMonitor(window, monitors[monitor], 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
TraceLog(LOG_INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
}
else TraceLog(LOG_WARNING, "Selected monitor not found");
@@ -708,7 +747,6 @@ int GetScreenHeight(void)
return screenHeight;
}
-#if !defined(PLATFORM_ANDROID)
// Show mouse cursor
void ShowCursor()
{
@@ -771,23 +809,21 @@ void DisableCursor()
#endif
cursorHidden = true;
}
-#endif // !defined(PLATFORM_ANDROID)
// Set background color (framebuffer clear color)
void ClearBackground(Color color)
{
- // Clear full framebuffer (not only render area) to color
- rlClearColor(color.r, color.g, color.b, color.a);
+ rlClearColor(color.r, color.g, color.b, color.a); // Set clear color
+ rlClearScreenBuffers(); // Clear current framebuffers
}
// Setup canvas (framebuffer) to start drawing
void BeginDrawing(void)
{
- currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called
+ currentTime = GetTime(); // Number of elapsed seconds since InitTimer()
updateTime = currentTime - previousTime;
previousTime = currentTime;
- rlClearScreenBuffers(); // Clear current framebuffers
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here
@@ -925,7 +961,7 @@ void BeginTextureMode(RenderTexture2D target)
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlEnableRenderTexture(target.id); // Enable render target
-
+
rlClearScreenBuffers(); // Clear render texture buffers
// Set viewport to framebuffer size
@@ -1057,6 +1093,24 @@ float GetFrameTime(void)
return (float)frameTime;
}
+// Get elapsed time measure in seconds since InitTimer()
+// NOTE: On PLATFORM_DESKTOP InitTimer() is called on InitWindow()
+// NOTE: On PLATFORM_DESKTOP, timer is initialized on glfwInit()
+double GetTime(void)
+{
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
+ return glfwGetTime(); // Elapsed time since glfwInit()
+#endif
+
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
+
+ return (double)(time - baseTime)*1e-9; // Elapsed time since InitTimer()
+#endif
+}
+
// Converts Color to float array and normalizes
float *ColorToFloat(Color color)
{
@@ -1108,9 +1162,7 @@ Color Fade(Color color, float alpha)
if (alpha < 0.0f) alpha = 0.0f;
else if (alpha > 1.0f) alpha = 1.0f;
- float colorAlpha = (float)color.a*alpha;
-
- return (Color){color.r, color.g, color.b, (unsigned char)colorAlpha};
+ return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)};
}
// Activate raylib logo at startup (can be done with flags)
@@ -1120,7 +1172,7 @@ void ShowLogo(void)
}
// Setup window configuration flags (view FLAGS)
-void SetConfigFlags(char flags)
+void SetConfigFlags(unsigned char flags)
{
configFlags = flags;
@@ -1156,7 +1208,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
return result;
}
-// Get the extension for a filename
+// Get pointer to extension for a filename string
const char *GetExtension(const char *fileName)
{
const char *dot = strrchr(fileName, '.');
@@ -1166,6 +1218,17 @@ const char *GetExtension(const char *fileName)
return (dot + 1);
}
+// Get pointer to filename for a path string
+const char *GetFileName(const char *filePath)
+{
+ const char *fileName = strrchr(filePath, '\\');
+
+ if (!fileName || fileName == filePath) return filePath;
+
+ return fileName + 1;
+}
+
+
// Get directory for a given fileName (with path)
const char *GetDirectoryPath(const char *fileName)
{
@@ -1646,7 +1709,8 @@ Vector2 GetTouchPosition(int index)
// Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
// If width or height are 0, default display size will be used for framebuffer size
-static void InitGraphicsDevice(int width, int height)
+// NOTE: returns false in case graphic device could not be created
+static bool InitGraphicsDevice(int width, int height)
{
screenWidth = width; // User desired width
screenHeight = height; // User desired height
@@ -1660,7 +1724,11 @@ static void InitGraphicsDevice(int width, int height)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSetErrorCallback(ErrorCallback);
- if (!glfwInit()) TraceLog(LOG_ERROR, "Failed to initialize GLFW");
+ if (!glfwInit())
+ {
+ TraceLog(LOG_WARNING, "Failed to initialize GLFW");
+ return false;
+ }
// NOTE: Getting video modes is not implemented in emscripten GLFW3 version
#if defined(PLATFORM_DESKTOP)
@@ -1771,24 +1839,28 @@ static void InitGraphicsDevice(int width, int height)
// No-fullscreen window creation
window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, NULL, NULL);
+ if (window)
+ {
#if defined(PLATFORM_DESKTOP)
- // Center window on screen
- int windowPosX = displayWidth/2 - screenWidth/2;
- int windowPosY = displayHeight/2 - screenHeight/2;
+ // Center window on screen
+ int windowPosX = displayWidth/2 - screenWidth/2;
+ int windowPosY = displayHeight/2 - screenHeight/2;
- if (windowPosX < 0) windowPosX = 0;
- if (windowPosY < 0) windowPosY = 0;
+ if (windowPosX < 0) windowPosX = 0;
+ if (windowPosY < 0) windowPosY = 0;
- glfwSetWindowPos(window, windowPosX, windowPosY);
+ glfwSetWindowPos(window, windowPosX, windowPosY);
#endif
- renderWidth = screenWidth;
- renderHeight = screenHeight;
+ renderWidth = screenWidth;
+ renderHeight = screenHeight;
+ }
}
if (!window)
{
glfwTerminate();
- TraceLog(LOG_ERROR, "GLFW Failed to initialize Window");
+ TraceLog(LOG_WARNING, "GLFW Failed to initialize Window");
+ return false;
}
else
{
@@ -1834,7 +1906,7 @@ static void InitGraphicsDevice(int width, int height)
}
#endif // defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
fullscreen = true;
// Screen size security check
@@ -1877,19 +1949,194 @@ static void InitGraphicsDevice(int width, int height)
EGL_NONE
};
- EGLint contextAttribs[] =
+ const EGLint contextAttribs[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
+#if defined(PLATFORM_UWP)
+ const EGLint surfaceAttributes[] =
+ {
+ // EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is part of the same optimization as EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER (see above).
+ // If you have compilation issues with it then please update your Visual Studio templates.
+ EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+ EGL_NONE
+ };
+
+ const EGLint defaultDisplayAttributes[] =
+ {
+ // These are the default display attributes, used to request ANGLE's D3D11 renderer.
+ // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+
+ // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
+ // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
+ EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+
+ // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
+ // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
+ // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
+ };
+
+ const EGLint fl9_3DisplayAttributes[] =
+ {
+ // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
+ // These attributes are used if the call to eglInitialize fails with the default display attributes.
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
+ EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
+ };
+
+ const EGLint warpDisplayAttributes[] =
+ {
+ // These attributes can be used to request D3D11 WARP.
+ // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
+ EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
+ };
+
+ EGLConfig config = NULL;
+
+ // eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11.
+ PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+ if (!eglGetPlatformDisplayEXT)
+ {
+ TraceLog(LOG_WARNING, "Failed to get function eglGetPlatformDisplayEXT");
+ return false;
+ }
+
+ //
+ // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying
+ // parameters passed to eglGetPlatformDisplayEXT:
+ // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+.
+ // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again
+ // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3.
+ // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again
+ // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer.
+ //
+
+ // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
+ display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
+ if (display == EGL_NO_DISPLAY)
+ {
+ TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ return false;
+ }
+
+ if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ {
+ // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
+ display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
+ if (display == EGL_NO_DISPLAY)
+ {
+ TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ return false;
+ }
+
+ if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ {
+ // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
+ display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
+ if (display == EGL_NO_DISPLAY)
+ {
+ TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ return false;
+ }
+
+ if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ {
+ // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
+ TraceLog(LOG_WARNING, "Failed to initialize EGL");
+ return false;
+ }
+ }
+ }
+
+ //SetupFramebufferSize(displayWidth, displayHeight);
+
+ EGLint numConfigs = 0;
+ if ((eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
+ {
+ TraceLog(LOG_WARNING, "Failed to choose first EGLConfig");
+ return false;
+ }
+
+ // Create a PropertySet and initialize with the EGLNativeWindowType.
+ //PropertySet^ surfaceCreationProperties = ref new PropertySet();
+ //surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), window); // CoreWindow^ window
+
+ // You can configure the surface to render at a lower resolution and be scaled up to
+ // the full window size. The scaling is often free on mobile hardware.
+ //
+ // One way to configure the SwapChainPanel is to specify precisely which resolution it should render at.
+ // Size customRenderSurfaceSize = Size(800, 600);
+ // surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(customRenderSurfaceSize));
+ //
+ // Another way is to tell the SwapChainPanel to render at a certain scale factor compared to its size.
+ // e.g. if the SwapChainPanel is 1920x1280 then setting a factor of 0.5f will make the app render at 960x640
+ // float customResolutionScale = 0.5f;
+ // surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(customResolutionScale));
+
+
+ // eglCreateWindowSurface() requires a EGLNativeWindowType parameter,
+ // In Windows platform: typedef HWND EGLNativeWindowType;
+
+
+ // Property: EGLNativeWindowTypeProperty
+ // Type: IInspectable
+ // Description: Set this property to specify the window type to use for creating a surface.
+ // If this property is missing, surface creation will fail.
+ //
+ //const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
+
+ //https://stackoverflow.com/questions/46550182/how-to-create-eglsurface-using-c-winrt-and-angle
+
+ //surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);
+ surface = eglCreateWindowSurface(display, config, uwpWindow, surfaceAttributes);
+ if (surface == EGL_NO_SURFACE)
+ {
+ TraceLog(LOG_WARNING, "Failed to create EGL fullscreen surface");
+ return false;
+ }
+
+ context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
+ if (context == EGL_NO_CONTEXT)
+ {
+ TraceLog(LOG_WARNING, "Failed to create EGL context");
+ return false;
+ }
+
+ // Get EGL display window size
+ eglQuerySurface(display, surface, EGL_WIDTH, &screenWidth);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &screenHeight);
+
+#else // PLATFORM_ANDROID, PLATFORM_RPI
EGLint numConfigs;
// Get an EGL display connection
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (display == EGL_NO_DISPLAY)
+ {
+ TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ return false;
+ }
// Initialize the EGL display connection
- eglInitialize(display, NULL, NULL);
+ if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ {
+ // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
+ TraceLog(LOG_WARNING, "Failed to initialize EGL");
+ return false;
+ }
// Get an appropriate EGL framebuffer configuration
eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs);
@@ -1899,6 +2146,12 @@ static void InitGraphicsDevice(int width, int height)
// Create an EGL rendering context
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
+ if (context == EGL_NO_CONTEXT)
+ {
+ TraceLog(LOG_WARNING, "Failed to create EGL context");
+ return false;
+ }
+#endif
// Create an EGL window surface
//---------------------------------------------------------------------------------
@@ -1966,7 +2219,8 @@ static void InitGraphicsDevice(int width, int height)
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
{
- TraceLog(LOG_ERROR, "Unable to attach EGL rendering context to EGL surface");
+ TraceLog(LOG_WARNING, "Unable to attach EGL rendering context to EGL surface");
+ return false;
}
else
{
@@ -1982,6 +2236,9 @@ static void InitGraphicsDevice(int width, int height)
}
#endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+ renderWidth = screenWidth;
+ renderHeight = screenHeight;
+
// Initialize OpenGL context (states and resources)
// NOTE: screenWidth and screenHeight not used, just stored as globals
rlglInit(screenWidth, screenHeight);
@@ -2002,6 +2259,7 @@ static void InitGraphicsDevice(int width, int height)
#if defined(PLATFORM_ANDROID)
windowReady = true; // IMPORTANT!
#endif
+ return true;
}
// Set viewport parameters
@@ -2117,22 +2375,6 @@ static void InitTimer(void)
previousTime = GetTime(); // Get time as double
}
-// Get current time measure (in seconds) since InitTimer()
-static double GetTime(void)
-{
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
- return glfwGetTime();
-#endif
-
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
-
- return (double)(time - baseTime)*1e-9;
-#endif
-}
-
// Wait for some milliseconds (stop program execution)
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
// take longer than expected... for that reason we use the busy wait loop
@@ -2366,7 +2608,7 @@ static void SwapBuffers(void)
glfwSwapBuffers(window);
#endif
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
eglSwapBuffers(display, surface);
#endif
}
@@ -2430,7 +2672,9 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
else
{
currentKeyState[key] = action;
- if (action == GLFW_PRESS) lastKeyPressed = key;
+
+ // NOTE: lastKeyPressed already registered on CharCallback()
+ //if (action == GLFW_PRESS) lastKeyPressed = key;
}
}
@@ -2496,12 +2740,15 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
#endif
}
-// GLFW3 Char Key Callback, runs on key pressed (get char value)
+// GLFW3 Char Key Callback, runs on key down (get unicode char value)
static void CharCallback(GLFWwindow *window, unsigned int key)
-{
+{
+ // NOTE: Registers any key down considering OS keyboard layout but
+ // do not detects action events, those should be managed by user...
+ // https://github.com/glfw/glfw/issues/668#issuecomment-166794907
+ // http://www.glfw.org/docs/latest/input_guide.html#input_char
+
lastKeyPressed = key;
-
- //TraceLog(LOG_INFO, "Char Callback Key pressed: %i\n", key);
}
// GLFW3 CursorEnter Callback, when cursor enters the window
@@ -2525,6 +2772,8 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
rlClearScreenBuffers(); // Clear screen buffers (color and depth)
// Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
+ // NOTE: Be careful! GLFW3 will choose the closest fullscreen resolution supported by current monitor,
+ // for example, if reescaling back to 800x450 (desired), it could set 720x480 (closest fullscreen supported)
screenWidth = width;
screenHeight = height;
renderWidth = width;
@@ -2599,6 +2848,9 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
{
// Init graphics device (display device and OpenGL context)
InitGraphicsDevice(screenWidth, screenHeight);
+
+ // Init hi-res timer
+ InitTimer();
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
@@ -2621,9 +2873,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
}
*/
- // Init hi-res timer
- InitTimer();
-
// raylib logo appearing animation (if enabled)
if (showLogo)
{
@@ -2776,8 +3025,16 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
ProcessGestureEvent(gestureEvent);
#else
- // TODO: Support only simple touch position
-
+ // Support only simple touch position
+ if (flags == AMOTION_EVENT_ACTION_DOWN)
+ {
+ // Get first touch position
+ touchPosition[0].x = AMotionEvent_getX(event, 0);
+ touchPosition[0].y = AMotionEvent_getY(event, 0);
+
+ touchPosition[0].x /= (float)GetScreenWidth();
+ touchPosition[0].y /= (float)GetScreenHeight();
+ }
#endif
return 0;