Update C sources and add new functions

This commit is contained in:
Milan Nikolic 2018-02-21 21:26:09 +01:00
parent 9784968948
commit 7874621942
24 changed files with 2149 additions and 1316 deletions

View file

@ -1,18 +1,16 @@
// +build !js
/**********************************************************************************************
*
* raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms
*
* PLATFORMS SUPPORTED:
* PLATFORM_DESKTOP: Windows (Win32, Win64)
* PLATFORM_DESKTOP: Linux (32 and 64 bit)
* PLATFORM_DESKTOP: OSX/macOS
* PLATFORM_DESKTOP: FreeBSD
* PLATFORM_ANDROID: Android (ARM, ARM64)
* PLATFORM_RPI: Raspberry Pi (Raspbian)
* PLATFORM_WEB: HTML5 (Chrome, Firefox)
* PLATFORM_UWP: Universal Windows Platform
* PLATFORMS SUPPORTED:
* - 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:
*
@ -32,6 +30,10 @@
* 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)
@ -91,7 +93,7 @@
#include "raylib.h"
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_S_SOURCE < 199309L
#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
@ -126,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
@ -152,11 +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)
__stdcall unsigned int timeBeginPeriod(unsigned int uPeriod);
__stdcall unsigned int timeEndPeriod(unsigned int uPeriod);
// NOTE: Those functions require linking with winmm library
unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif
#endif
@ -187,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>
@ -226,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
@ -264,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
@ -273,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)
@ -281,12 +294,11 @@ static int renderOffsetX = 0; // Offset X from render area (must b
static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2)
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)
static bool cursorHidden = false; // Track if cursor is hidden
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
static const char *windowTitle = NULL; // 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 int screenshotCounter = 0; // Screenshots counter
// Register mouse states
@ -331,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)
@ -350,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
@ -403,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()
@ -411,18 +426,28 @@ 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
// 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.9-dev)");
TraceLog(LOG_INFO, "Initializing raylib (v1.9.4-dev)");
// Input data is window title char data
#if defined(PLATFORM_DESKTOP)
windowTitle = (char *)data;
#endif
#if defined(PLATFORM_UWP)
uwpWindow = (EGLNativeWindowType)data;
#endif
// Init hi-res timer
InitTimer();
// 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);
if (!windowReady) return;
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -430,9 +455,6 @@ void InitWindow(int width, int height, void *data)
LoadDefaultFont();
#endif
// Init hi-res timer
InitTimer();
#if defined(PLATFORM_RPI)
// Init raw input system
InitMouse(); // Mouse init
@ -480,7 +502,7 @@ void InitWindow(int width, int height, void *data)
// 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.9-dev)");
TraceLog(LOG_INFO, "Initializing raylib (v1.9.4-dev)");
screenWidth = width;
screenHeight = height;
@ -564,7 +586,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)
{
@ -602,25 +624,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;
@ -687,7 +720,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");
@ -781,18 +814,17 @@ void DisableCursor()
// 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
@ -930,7 +962,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
@ -1062,7 +1094,25 @@ float GetFrameTime(void)
return (float)frameTime;
}
// Converts Color to float array and normalizes
// 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
}
// Returns normalized float array for a Color
float *ColorToFloat(Color color)
{
static float buffer[4];
@ -1075,6 +1125,64 @@ float *ColorToFloat(Color color)
return buffer;
}
// Returns hexadecimal value for a Color
int ColorToInt(Color color)
{
return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
}
// Returns HSV values for a Color
// NOTE: Hue is returned as degrees [0..360]
Vector3 ColorToHSV(Color color)
{
Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
Vector3 hsv = { 0.0f, 0.0f, 0.0f };
float min, max, delta;
min = rgb.x < rgb.y ? rgb.x : rgb.y;
min = min < rgb.z ? min : rgb.z;
max = rgb.x > rgb.y ? rgb.x : rgb.y;
max = max > rgb.z ? max : rgb.z;
hsv.z = max; // Value
delta = max - min;
if (delta < 0.00001f)
{
hsv.y = 0.0f;
hsv.x = 0.0f; // Undefined, maybe NAN?
return hsv;
}
if (max > 0.0f)
{
// NOTE: If max is 0, this divide would cause a crash
hsv.y = (delta/max); // Saturation
}
else
{
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
hsv.y = 0.0f;
hsv.x = NAN; // Undefined
return hsv;
}
// NOTE: Comparing float values could not work properly
if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
else
{
if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
}
hsv.x *= 60.0f; // Convert to degrees
if (hsv.x < 0.0f) hsv.x += 360.0f;
return hsv;
}
// Returns a Color struct from hexadecimal value
Color GetColor(int hexValue)
{
@ -1088,11 +1196,7 @@ Color GetColor(int hexValue)
return color;
}
// Returns hexadecimal value for a Color
int GetHexValue(Color color)
{
return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
}
// Returns a random value between min and max (both included)
int GetRandomValue(int min, int max)
@ -1123,7 +1227,7 @@ void ShowLogo(void)
}
// Setup window configuration flags (view FLAGS)
void SetConfigFlags(char flags)
void SetConfigFlags(unsigned char flags)
{
configFlags = flags;
@ -1159,7 +1263,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, '.');
@ -1169,6 +1273,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)
{
@ -1649,7 +1764,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
@ -1663,12 +1779,22 @@ 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)
// Find monitor resolution
const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
if (!monitor)
{
TraceLog(LOG_WARNING, "Failed to get monitor");
return false;
}
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
displayWidth = mode->width;
displayHeight = mode->height;
@ -1774,24 +1900,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
{
@ -1837,7 +1967,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
@ -1880,19 +2010,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);
@ -1902,6 +2207,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
//---------------------------------------------------------------------------------
@ -1969,7 +2280,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
{
@ -1985,6 +2297,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);
@ -2005,6 +2320,7 @@ static void InitGraphicsDevice(int width, int height)
#if defined(PLATFORM_ANDROID)
windowReady = true; // IMPORTANT!
#endif
return true;
}
// Set viewport parameters
@ -2120,22 +2436,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
@ -2369,7 +2669,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
}
@ -2433,7 +2733,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;
}
}
@ -2499,12 +2801,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
@ -2604,6 +2909,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
@ -2626,9 +2934,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
}
*/
// Init hi-res timer
InitTimer();
// raylib logo appearing animation (if enabled)
if (showLogo)
{