Merge pull request #3 from raysan5/master

Merge upstream changes
This commit is contained in:
MichaelFiber 2023-10-14 13:40:46 -04:00 committed by GitHub
commit e23da390bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 10935 additions and 3354 deletions

View File

@ -81,6 +81,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| rayed-bqn | **auto** | [BQN](https://mlochbaum.github.io/BQN/) | MIT | https://github.com/Brian-ED/rayed-bqn | | rayed-bqn | **auto** | [BQN](https://mlochbaum.github.io/BQN/) | MIT | https://github.com/Brian-ED/rayed-bqn |
| rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs | | rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs |
| raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku | | raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku |
| Raylib.lean | 4.5 | [Lean4](https://lean-lang.org/) | BSD-3-Clause | https://github.com/KislyjKisel/Raylib.lean |
### Utility Wrapers ### Utility Wrapers
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm. These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm.

View File

@ -1,7 +1,7 @@
const std = @import("std"); const std = @import("std");
const raylib = @import("src/build.zig"); const raylib = @import("src/build.zig");
// This has been tested to work with zig master branch as of commit 87de821 or May 14 2023 // This has been tested to work with zig 0.11.0 (67709b6, Aug 4 2023)
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
raylib.build(b); raylib.build(b);
} }

View File

@ -1,7 +1,7 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
// This has been tested to work with zig master branch as of commit 87de821 or May 14 2023 // This has been tested to work with zig 0.11.0 (67709b6, Aug 4 2023)
fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step { fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step {
if (target.getOsTag() == .emscripten) { if (target.getOsTag() == .emscripten) {
@panic("Emscripten building via Zig unsupported"); @panic("Emscripten building via Zig unsupported");
@ -11,7 +11,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossT
const dir = try std.fs.cwd().openIterableDir(module, .{}); const dir = try std.fs.cwd().openIterableDir(module, .{});
var iter = dir.iterate(); var iter = dir.iterate();
while (try iter.next()) |entry| { while (try iter.next()) |entry| {
if (entry.kind != .File) continue; if (entry.kind != .file) continue;
const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue; const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue;
const name = entry.name[0..extension_idx]; const name = entry.name[0..extension_idx];
const path = try std.fs.path.join(b.allocator, &.{ module, entry.name }); const path = try std.fs.path.join(b.allocator, &.{ module, entry.name });
@ -24,26 +24,26 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossT
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
exe.addCSourceFile(path, &[_][]const u8{}); exe.addCSourceFile(.{ .file = .{ .path = path }, .flags = &.{} });
exe.linkLibC(); exe.linkLibC();
exe.addObjectFile(switch (target.getOsTag()) { exe.addObjectFile(switch (target.getOsTag()) {
.windows => "../src/zig-out/lib/raylib.lib", .windows => .{ .path = "../zig-out/lib/raylib.lib" },
.linux => "../src/zig-out/lib/libraylib.a", .linux => .{ .path = "../zig-out/lib/libraylib.a" },
.macos => "../src/zig-out/lib/libraylib.a", .macos => .{ .path = "../zig-out/lib/libraylib.a" },
.emscripten => "../src/zig-out/lib/libraylib.a", .emscripten => .{ .path = "../zig-out/lib/libraylib.a" },
else => @panic("Unsupported OS"), else => @panic("Unsupported OS"),
}); });
exe.addIncludePath("../src"); exe.addIncludePath(.{ .path = "../src" });
exe.addIncludePath("../src/external"); exe.addIncludePath(.{ .path = "../src/external" });
exe.addIncludePath("../src/external/glfw/include"); exe.addIncludePath(.{ .path = "../src/external/glfw/include" });
switch (target.getOsTag()) { switch (target.getOsTag()) {
.windows => { .windows => {
exe.linkSystemLibrary("winmm"); exe.linkSystemLibrary("winmm");
exe.linkSystemLibrary("gdi32"); exe.linkSystemLibrary("gdi32");
exe.linkSystemLibrary("opengl32"); exe.linkSystemLibrary("opengl32");
exe.addIncludePath("external/glfw/deps/mingw"); exe.addIncludePath(.{ .path = "external/glfw/deps/mingw" });
exe.defineCMacro("PLATFORM_DESKTOP", null); exe.defineCMacro("PLATFORM_DESKTOP", null);
}, },
@ -71,11 +71,15 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossT
}, },
} }
b.installArtifact(exe); const install_cmd = b.addInstallArtifact(exe, .{});
var run = b.addRunArtifact(exe);
run.cwd = module; const run_cmd = b.addRunArtifact(exe);
b.step(name, name).dependOn(&run.step); run_cmd.step.dependOn(&install_cmd.step);
all.dependOn(&exe.step);
const run_step = b.step(name, name);
run_step.dependOn(&run_cmd.step);
all.dependOn(&install_cmd.step);
} }
return all; return all;
} }

View File

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
// This has been tested to work with zig master branch as of commit 87de821 or May 14 2023 // This has been tested to work with zig 0.11.0 (67709b6, Aug 4 2023)
pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode, options: Options) *std.Build.CompileStep { pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode, options: Options) *std.Build.CompileStep {
const raylib_flags = &[_][]const u8{ const raylib_flags = &[_][]const u8{
"-std=gnu99", "-std=gnu99",

File diff suppressed because it is too large Load Diff

10303
src/external/stb_image_resize2.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -981,14 +981,14 @@ void UnloadSoundAlias(Sound alias)
} }
// Update sound buffer with new data // Update sound buffer with new data
void UpdateSound(Sound sound, const void *data, int sampleCount) void UpdateSound(Sound sound, const void *data, int frameCount)
{ {
if (sound.stream.buffer != NULL) if (sound.stream.buffer != NULL)
{ {
StopAudioBuffer(sound.stream.buffer); StopAudioBuffer(sound.stream.buffer);
// TODO: May want to lock/unlock this since this data buffer is read at mixing time // TODO: May want to lock/unlock this since this data buffer is read at mixing time
memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn)); memcpy(sound.stream.buffer->data, data, frameCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
} }
} }

View File

@ -322,18 +322,15 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
//void InitWindow(int width, int height, const char *title) //void InitWindow(int width, int height, const char *title)
//void CloseWindow(void) //void CloseWindow(void)
//bool WindowShouldClose(void) //bool WindowShouldClose(void)
//bool IsWindowHidden(void)
//bool IsWindowMinimized(void)
//bool IsWindowMaximized(void)
//bool IsWindowFocused(void)
//bool IsWindowResized(void)
//void ToggleFullscreen(void) //void ToggleFullscreen(void)
//void ToggleBorderlessWindowed(void)
//void MaximizeWindow(void) //void MaximizeWindow(void)
//void MinimizeWindow(void) //void MinimizeWindow(void)
//void RestoreWindow(void) //void RestoreWindow(void)
//void ToggleBorderlessWindowed(void)
//void SetWindowState(unsigned int flags) //void SetWindowState(unsigned int flags)
//void ClearWindowState(unsigned int flags) //void ClearWindowState(unsigned int flags)
//void SetWindowIcon(Image image) //void SetWindowIcon(Image image)
//void SetWindowIcons(Image *images, int count) //void SetWindowIcons(Image *images, int count)
//void SetWindowTitle(const char *title) //void SetWindowTitle(const char *title)
@ -345,25 +342,27 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
//void SetWindowOpacity(float opacity) //void SetWindowOpacity(float opacity)
//void SetWindowFocused(void) //void SetWindowFocused(void)
//void *GetWindowHandle(void) //void *GetWindowHandle(void)
//Vector2 GetWindowPosition(void)
//Vector2 GetWindowScaleDPI(void)
//int GetMonitorCount(void) //int GetMonitorCount(void)
//int GetCurrentMonitor(void) //int GetCurrentMonitor(void)
//Vector2 GetMonitorPosition(int monitor)
//int GetMonitorWidth(int monitor) //int GetMonitorWidth(int monitor)
//int GetMonitorHeight(int monitor) //int GetMonitorHeight(int monitor)
//int GetMonitorPhysicalWidth(int monitor) //int GetMonitorPhysicalWidth(int monitor)
//int GetMonitorPhysicalHeight(int monitor) //int GetMonitorPhysicalHeight(int monitor)
//int GetMonitorRefreshRate(int monitor) //int GetMonitorRefreshRate(int monitor)
//Vector2 GetMonitorPosition(int monitor)
//const char *GetMonitorName(int monitor) //const char *GetMonitorName(int monitor)
//Vector2 GetWindowPosition(void)
//Vector2 GetWindowScaleDPI(void)
//void SetClipboardText(const char *text) //void SetClipboardText(const char *text)
//const char *GetClipboardText(void) //const char *GetClipboardText(void)
//void ShowCursor(void) //void ShowCursor(void)
//void HideCursor(void) //void HideCursor(void)
//void EnableCursor(void) //void EnableCursor(void)
//void DisableCursor(void) //void DisableCursor(void)
// Check if window has been initialized successfully // Check if window has been initialized successfully
bool IsWindowReady(void) bool IsWindowReady(void)
{ {
@ -376,6 +375,36 @@ bool IsWindowFullscreen(void)
return CORE.Window.fullscreen; return CORE.Window.fullscreen;
} }
// Check if window is currently hidden
bool IsWindowHidden(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0);
}
// Check if window has been minimized
bool IsWindowMinimized(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0);
}
// Check if window has been maximized
bool IsWindowMaximized(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0);
}
// Check if window has the focus
bool IsWindowFocused(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
}
// Check if window has been resizedLastFrame
bool IsWindowResized(void)
{
return CORE.Window.resizedLastFrame;
}
// Check if one specific window flag is enabled // Check if one specific window flag is enabled
bool IsWindowState(unsigned int flag) bool IsWindowState(unsigned int flag)
{ {
@ -394,13 +423,13 @@ int GetScreenHeight(void)
return CORE.Window.screen.height; return CORE.Window.screen.height;
} }
// Get current render width which is equal to screen width * dpi scale // Get current render width which is equal to screen width*dpi scale
int GetRenderWidth(void) int GetRenderWidth(void)
{ {
return CORE.Window.render.width; return CORE.Window.render.width;
} }
// Get current screen height which is equal to screen height * dpi scale // Get current screen height which is equal to screen height*dpi scale
int GetRenderHeight(void) int GetRenderHeight(void)
{ {
return CORE.Window.render.height; return CORE.Window.render.height;
@ -2331,15 +2360,15 @@ int GetTouchPointCount(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c // NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
//static bool InitGraphicsDevice(int width, int height) //static bool InitPlatform(void)
// Initialize hi-resolution timer // Initialize hi-resolution timer
void InitTimer(void) void InitTimer(void)
{ {
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
// High resolutions can also prevent the CPU power management system from entering power-saving modes. // High resolutions can also prevent the CPU power management system from entering power-saving modes.
// Setting a higher resolution does not improve the accuracy of the high-resolution performance counter. // Setting a higher resolution does not improve the accuracy of the high-resolution performance counter.
#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)
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
@ -2783,7 +2812,7 @@ static void RecordAutomationEvent(unsigned int frame)
// INPUT_GAMEPAD_CONNECT // INPUT_GAMEPAD_CONNECT
/* /*
if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) && if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) &&
(CORE.Input.Gamepad.currentState[gamepad] == true)) // Check if changed to ready (CORE.Input.Gamepad.currentState[gamepad])) // Check if changed to ready
{ {
// TODO: Save gamepad connect event // TODO: Save gamepad connect event
} }
@ -2792,7 +2821,7 @@ static void RecordAutomationEvent(unsigned int frame)
// INPUT_GAMEPAD_DISCONNECT // INPUT_GAMEPAD_DISCONNECT
/* /*
if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) && if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) &&
(CORE.Input.Gamepad.currentState[gamepad] == false)) // Check if changed to not-ready (!CORE.Input.Gamepad.currentState[gamepad])) // Check if changed to not-ready
{ {
// TODO: Save gamepad disconnect event // TODO: Save gamepad disconnect event
} }

View File

@ -82,7 +82,8 @@ static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
static void ClosePlatform(void); // Close platform
static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs
@ -172,81 +173,23 @@ void InitWindow(int width, int height, const char *title)
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)"); TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
#endif #endif
// NOTE: Keep internal pointer to input title string (no copy) // Initialize window data
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
CORE.Window.eventWaiting = false;
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
// Initialize global input state // Initialize global input state
memset(&CORE.Input, 0, sizeof(CORE.Input)); memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
CORE.Input.Keyboard.exitKey = KEY_ESCAPE; CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f }; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
CORE.Window.eventWaiting = false;
CORE.Window.screen.width = width; // Initialize platform
CORE.Window.screen.height = height; //--------------------------------------------------------------
CORE.Window.currentFbo.width = width; InitPlatform();
CORE.Window.currentFbo.height = height;
// Platform specific init window
//--------------------------------------------------------------
// Set desired windows flags before initializing anything
ANativeActivity_setWindowFlags(platform.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
int orientation = AConfiguration_getOrientation(platform.app->config);
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");
// TODO: Automatic orientation doesn't seem to work
if (width <= height)
{
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_PORT);
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
}
else
{
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_LAND);
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
}
//AConfiguration_getDensity(platform.app->config);
//AConfiguration_getKeyboard(platform.app->config);
//AConfiguration_getScreenSize(platform.app->config);
//AConfiguration_getScreenLong(platform.app->config);
// Initialize App command system
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
platform.app->onAppCmd = AndroidCommandCallback;
// Initialize input events system
platform.app->onInputEvent = AndroidInputCallback;
// Initialize assets manager
InitAssetManager(platform.app->activity->assetManager, platform.app->activity->internalDataPath);
// Initialize base path for storage
CORE.Storage.basePath = platform.app->activity->internalDataPath;
TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Application initialized successfully");
// Android ALooper_pollAll() variables
int pollResult = 0;
int pollEvents = 0;
// Wait for window to be initialized (display and context)
while (!CORE.Window.ready)
{
// Process events loop
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)
{
// Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Never close window, native activity is controlled by the system!
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
}
}
//-------------------------------------------------------------- //--------------------------------------------------------------
} }
@ -272,28 +215,9 @@ void CloseWindow(void)
timeEndPeriod(1); // Restore time period timeEndPeriod(1); // Restore time period
#endif #endif
// Platform specific close window // De-initialize platform
//-------------------------------------------------------------- //--------------------------------------------------------------
// Close surface, context and display ClosePlatform();
if (platform.device != EGL_NO_DISPLAY)
{
eglMakeCurrent(platform.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (platform.surface != EGL_NO_SURFACE)
{
eglDestroySurface(platform.device, platform.surface);
platform.surface = EGL_NO_SURFACE;
}
if (platform.context != EGL_NO_CONTEXT)
{
eglDestroyContext(platform.device, platform.context);
platform.context = EGL_NO_CONTEXT;
}
eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY;
}
//-------------------------------------------------------------- //--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
@ -311,36 +235,6 @@ bool WindowShouldClose(void)
else return true; else return true;
} }
// Check if window is currently hidden
bool IsWindowHidden(void)
{
return false;
}
// Check if window has been minimized
bool IsWindowMinimized(void)
{
return false;
}
// Check if window has been maximized
bool IsWindowMaximized(void)
{
return false;
}
// Check if window has the focus
bool IsWindowFocused(void)
{
return platform.appEnabled;
}
// Check if window has been resizedLastFrame
bool IsWindowResized(void)
{
return false;
}
// Toggle fullscreen mode // Toggle fullscreen mode
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
@ -713,25 +607,108 @@ void PollInputEvents(void)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize platform: graphics, inputs and more
static int InitPlatform(void)
{
CORE.Window.currentFbo.width = CORE.Window.screen.width;
CORE.Window.currentFbo.height = CORE.Window.screen.height;
// Set desired windows flags before initializing anything
ANativeActivity_setWindowFlags(platform.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
int orientation = AConfiguration_getOrientation(platform.app->config);
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");
// TODO: Automatic orientation doesn't seem to work
if (CORE.Window.screen.width <= CORE.Window.screen.height)
{
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_PORT);
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
}
else
{
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_LAND);
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
}
//AConfiguration_getDensity(platform.app->config);
//AConfiguration_getKeyboard(platform.app->config);
//AConfiguration_getScreenSize(platform.app->config);
//AConfiguration_getScreenLong(platform.app->config);
// Initialize App command system
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
platform.app->onAppCmd = AndroidCommandCallback;
// Initialize input events system
platform.app->onInputEvent = AndroidInputCallback;
// Initialize assets manager
InitAssetManager(platform.app->activity->assetManager, platform.app->activity->internalDataPath);
// Initialize base path for storage
CORE.Storage.basePath = platform.app->activity->internalDataPath;
// Set some default window flags
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // false
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Application initialized successfully");
// Android ALooper_pollAll() variables
int pollResult = 0;
int pollEvents = 0;
// Wait for window to be initialized (display and context)
while (!CORE.Window.ready)
{
// Process events loop
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)
{
// Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Never close window, native activity is controlled by the system!
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
}
}
}
// Close platform
static void ClosePlatform(void)
{
// Close surface, context and display
if (platform.device != EGL_NO_DISPLAY)
{
eglMakeCurrent(platform.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (platform.surface != EGL_NO_SURFACE)
{
eglDestroySurface(platform.device, platform.surface);
platform.surface = EGL_NO_SURFACE;
}
if (platform.context != EGL_NO_CONTEXT)
{
eglDestroyContext(platform.device, platform.context);
platform.context = EGL_NO_CONTEXT;
}
eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY;
}
}
// Initialize display device and framebuffer // Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size // 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 // If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created // NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height) static bool InitGraphicsDevice(void)
{ {
CORE.Window.screen.width = width; // User desired width
CORE.Window.screen.height = height; // User desired height
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
// Set the screen minimum and maximum default values to 0
CORE.Window.screenMin.width = 0;
CORE.Window.screenMin.height = 0;
CORE.Window.screenMax.width = 0;
CORE.Window.screenMax.height = 0;
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
CORE.Window.fullscreen = true; CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE; CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
@ -771,7 +748,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.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 -1;
} }
// Initialize the EGL device connection // Initialize the EGL device connection
@ -779,7 +756,7 @@ static bool InitGraphicsDevice(int width, int height)
{ {
// 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 -1;
} }
// Get an appropriate EGL framebuffer configuration // Get an appropriate EGL framebuffer configuration
@ -793,7 +770,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.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 -1;
} }
// Create an EGL window surface // Create an EGL window surface
@ -822,7 +799,7 @@ static bool InitGraphicsDevice(int width, int height)
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.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 -1;
} }
else else
{ {
@ -842,19 +819,11 @@ static bool InitGraphicsDevice(int width, int height)
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(eglGetProcAddress); rlLoadExtensions(eglGetProcAddress);
// Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
CORE.Window.ready = true; CORE.Window.ready = true;
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
return true; return 0;
} }
// ANDROID: Process activity lifecycle commands // ANDROID: Process activity lifecycle commands
@ -897,24 +866,49 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
CORE.Window.display.height = ANativeWindow_getHeight(platform.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();
// Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize hi-res timer // Initialize hi-res timer
InitTimer(); InitTimer();
// Initialize random seed
srand((unsigned int)time(NULL));
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font // Load default font
// WARNING: External function: Module required: rtext // WARNING: External function: Module required: rtext
LoadFontDefault(); LoadFontDefault();
Rectangle rec = GetFontDefault().recs[95];
// NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
#if defined(SUPPORT_MODULE_RSHAPES) #if defined(SUPPORT_MODULE_RSHAPES)
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes // Set font white rectangle for shapes drawing, so shapes and text can be batched together
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
Rectangle rec = GetFontDefault().recs[95];
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
{
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
}
else
{
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
}
#endif
#else
#if defined(SUPPORT_MODULE_RSHAPES)
// Set default texture and rectangle to be used for shapes drawing
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
#endif #endif
#endif #endif
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// TODO: GPU assets reload in case of lost focus (lost context) // TODO: GPU assets reload in case of lost focus (lost context)
// NOTE: This problem has been solved just unbinding and rebinding context from display // NOTE: This problem has been solved just unbinding and rebinding context from display
@ -936,12 +930,14 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
case APP_CMD_GAINED_FOCUS: case APP_CMD_GAINED_FOCUS:
{ {
platform.appEnabled = true; platform.appEnabled = true;
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
//ResumeMusicStream(); //ResumeMusicStream();
} break; } break;
case APP_CMD_PAUSE: break; case APP_CMD_PAUSE: break;
case APP_CMD_LOST_FOCUS: case APP_CMD_LOST_FOCUS:
{ {
platform.appEnabled = false; platform.appEnabled = false;
CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
//PauseMusicStream(); //PauseMusicStream();
} break; } break;
case APP_CMD_TERM_WINDOW: case APP_CMD_TERM_WINDOW:
@ -1173,6 +1169,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{ {
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i]; gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
gestureEvent.position[i] = CORE.Input.Touch.position[i]; gestureEvent.position[i] = CORE.Input.Touch.position[i];
gestureEvent.position[i].x /= (float)GetScreenWidth();
gestureEvent.position[i].y /= (float)GetScreenHeight();
} }
// Gesture data is sent to gestures system for processing // Gesture data is sent to gestures system for processing
@ -1199,6 +1197,16 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1; if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0; else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
// Stores the previous position of touch[0] only while it's active to calculate the delta.
if (flags == AMOTION_EVENT_ACTION_MOVE)
{
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
else
{
CORE.Input.Mouse.previousPosition = CORE.Input.Touch.position[0];
}
// Map touch[0] as mouse input for convenience // Map touch[0] as mouse input for convenience
CORE.Input.Mouse.currentPosition = CORE.Input.Touch.position[0]; CORE.Input.Mouse.currentPosition = CORE.Input.Touch.position[0];
CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f }; CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f };

View File

@ -2,7 +2,7 @@
* *
* rcore_desktop - Functions to manage window, graphics device and inputs * rcore_desktop - Functions to manage window, graphics device and inputs
* *
* PLATFORM: DESKTOP * PLATFORM: DESKTOP: GLFW
* - Windows (Win32, Win64) * - Windows (Win32, Win64)
* - Linux (X11/Wayland desktop mode) * - Linux (X11/Wayland desktop mode)
* - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop) * - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
@ -111,7 +111,8 @@ static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
static void ClosePlatform(void); // Close platform
// Error callback event // Error callback event
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
@ -176,33 +177,31 @@ void InitWindow(int width, int height, const char *title)
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)"); TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
#endif #endif
// NOTE: Keep internal pointer to input title string (no copy) // Initialize window data
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
CORE.Window.eventWaiting = false;
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
// Initialize global input state // Initialize global input state
memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE structure to 0 memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
CORE.Input.Keyboard.exitKey = KEY_ESCAPE; CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f }; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
CORE.Window.eventWaiting = false;
// Initialize platform
//--------------------------------------------------------------
InitPlatform();
//--------------------------------------------------------------
// Initialize rlgl default data (buffers and shaders)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize graphics device // Setup default viewport
// NOTE: returns true if window and graphic device has been initialized successfully SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
CORE.Window.ready = InitGraphicsDevice(width, height);
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
// Initialize hi-res timer
InitTimer();
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font // Load default font
@ -246,6 +245,9 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
#endif #endif
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: Application initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: Application initialized successfully");
} }
@ -267,14 +269,9 @@ void CloseWindow(void)
rlglClose(); // De-init rlgl rlglClose(); // De-init rlgl
// Platform specific close window // De-initialize platform
//-------------------------------------------------------------- //--------------------------------------------------------------
glfwDestroyWindow(platform.handle); ClosePlatform();
glfwTerminate();
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
timeEndPeriod(1); // Restore time period
#endif
//-------------------------------------------------------------- //--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
@ -304,36 +301,6 @@ bool WindowShouldClose(void)
else return true; else return true;
} }
// Check if window is currently hidden
bool IsWindowHidden(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0);
}
// Check if window has been minimized
bool IsWindowMinimized(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0);
}
// Check if window has been maximized
bool IsWindowMaximized(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0);
}
// Check if window has the focus
bool IsWindowFocused(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
}
// Check if window has been resizedLastFrame
bool IsWindowResized(void)
{
return CORE.Window.resizedLastFrame;
}
// Toggle fullscreen mode // Toggle fullscreen mode
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
@ -1389,25 +1356,9 @@ void PollInputEvents(void)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize display device and framebuffer // Initialize platform: graphics, inputs and more
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size static int InitPlatform(void)
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
{ {
CORE.Window.screen.width = width; // User desired width
CORE.Window.screen.height = height; // User desired height
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
// Set the screen minimum and maximum default values to 0
CORE.Window.screenMin.width = 0;
CORE.Window.screenMin.height = 0;
CORE.Window.screenMax.width = 0;
CORE.Window.screenMax.height = 0;
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
glfwSetErrorCallback(ErrorCallback); glfwSetErrorCallback(ErrorCallback);
/* /*
// TODO: Setup GLFW custom allocators to match raylib ones // TODO: Setup GLFW custom allocators to match raylib ones
@ -1420,15 +1371,13 @@ static bool InitGraphicsDevice(int width, int height)
glfwInitAllocator(&allocator); glfwInitAllocator(&allocator);
*/ */
#if defined(__APPLE__) #if defined(__APPLE__)
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
#endif #endif
// Initialize GLFW internal global state
if (!glfwInit()) int result = glfwInit();
{ if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW");
return false;
}
glfwDefaultWindowHints(); // Set default windows hints glfwDefaultWindowHints(); // Set default windows hints
//glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
@ -1550,7 +1499,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!monitor) if (!monitor)
{ {
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor"); TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
return false; return -1;
} }
const GLFWvidmode *mode = glfwGetVideoMode(monitor); const GLFWvidmode *mode = glfwGetVideoMode(monitor);
@ -1639,7 +1588,7 @@ static bool InitGraphicsDevice(int width, int height)
{ {
glfwTerminate(); glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window"); TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return false; return -1;
} }
// Set window callback events // Set window callback events
@ -1705,22 +1654,37 @@ static bool InitGraphicsDevice(int width, int height)
// Load OpenGL extensions // Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(glfwGetProcAddress); rlLoadExtensions(glfwGetProcAddress);
// Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
return true; CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
// Initialize hi-res timer
InitTimer();
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
return 0;
} }
// Close platform
static void ClosePlatform(void)
{
glfwDestroyWindow(platform.handle);
glfwTerminate();
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
timeEndPeriod(1); // Restore time period
#endif
}
// GLFW3 Error Callback, runs on GLFW3 error // GLFW3 Error Callback, runs on GLFW3 error
static void ErrorCallback(int error, const char *description) static void ErrorCallback(int error, const char *description)
{ {
@ -1988,7 +1952,7 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
// GLFW3 CursorEnter Callback, when cursor enters the window // GLFW3 CursorEnter Callback, when cursor enters the window
static void CursorEnterCallback(GLFWwindow *window, int enter) static void CursorEnterCallback(GLFWwindow *window, int enter)
{ {
if (enter == true) CORE.Input.Mouse.cursorOnScreen = true; if (enter) CORE.Input.Mouse.cursorOnScreen = true;
else CORE.Input.Mouse.cursorOnScreen = false; else CORE.Input.Mouse.cursorOnScreen = false;
} }

View File

@ -140,21 +140,22 @@ static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
static void ClosePlatform(void); // Close platform
static void InitKeyboard(void); // Initialize raw keyboard system static void InitKeyboard(void); // Initialize raw keyboard system
static void RestoreKeyboard(void); // Restore keyboard system static void RestoreKeyboard(void); // Restore keyboard system
#if defined(SUPPORT_SSH_KEYBOARD_RPI) #if defined(SUPPORT_SSH_KEYBOARD_RPI)
static void ProcessKeyboard(void); // Process keyboard events static void ProcessKeyboard(void); // Process keyboard events
#endif #endif
static void InitEvdevInput(void); // Initialize evdev inputs static void InitEvdevInput(void); // Initialize evdev inputs
static void ConfigureEvdevDevice(char *device); // Identifies a input device and configures it for use if appropriate static void ConfigureEvdevDevice(char *device); // Identifies a input device and configures it for use if appropriate
static void PollKeyboardEvents(void); // Process evdev keyboard events static void PollKeyboardEvents(void); // Process evdev keyboard events
static void *EventThread(void *arg); // Input device events reading thread static void *EventThread(void *arg); // Input device events reading thread
static void InitGamepad(void); // Initialize raw gamepad input static void InitGamepad(void); // Initialize raw gamepad input
static void *GamepadThread(void *arg); // Mouse reading thread static void *GamepadThread(void *arg); // Mouse reading thread
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
@ -204,33 +205,31 @@ void InitWindow(int width, int height, const char *title)
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)"); TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
#endif #endif
// NOTE: Keep internal pointer to input title string (no copy) // Initialize window data
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
CORE.Window.eventWaiting = false;
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
// Initialize global input state // Initialize global input state
memset(&CORE.Input, 0, sizeof(CORE.Input)); memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
CORE.Input.Keyboard.exitKey = KEY_ESCAPE; CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
CORE.Input.Mouse.scale = (Vector2){1.0f, 1.0f}; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
CORE.Window.eventWaiting = false;
// Initialize platform
//--------------------------------------------------------------
InitPlatform();
//--------------------------------------------------------------
// Initialize rlgl default data (buffers and shaders)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize graphics device (display device and OpenGL context) // Setup default viewport
// NOTE: returns true if window and graphic device has been initialized successfully SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
CORE.Window.ready = InitGraphicsDevice(width, height);
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
// Initialize hi-res timer
InitTimer();
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font // Load default font
@ -273,15 +272,10 @@ void InitWindow(int width, int height, const char *title)
events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent)); events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent));
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
#endif #endif
// Platform specific init window // Initialize random seed
//-------------------------------------------------------------- SetRandomSeed((unsigned int)time(NULL));
// Initialize raw input system
InitEvdevInput(); // Evdev inputs initialization
InitGamepad(); // Gamepad init
InitKeyboard(); // Keyboard init (stdin)
//--------------------------------------------------------------
TRACELOG(LOG_INFO, "PLATFORM: DRM: Application initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DRM: Application initialized successfully");
} }
@ -307,93 +301,9 @@ void CloseWindow(void)
timeEndPeriod(1); // Restore time period timeEndPeriod(1); // Restore time period
#endif #endif
// Platform specific close window // De-initialize platform
//-------------------------------------------------------------- //--------------------------------------------------------------
if (platform.prevFB) ClosePlatform();
{
drmModeRmFB(platform.fd, platform.prevFB);
platform.prevFB = 0;
}
if (platform.prevBO)
{
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
platform.prevBO = NULL;
}
if (platform.gbmSurface)
{
gbm_surface_destroy(platform.gbmSurface);
platform.gbmSurface = NULL;
}
if (platform.gbmDevice)
{
gbm_device_destroy(platform.gbmDevice);
platform.gbmDevice = NULL;
}
if (platform.crtc)
{
if (platform.connector)
{
drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
drmModeFreeConnector(platform.connector);
platform.connector = NULL;
}
drmModeFreeCrtc(platform.crtc);
platform.crtc = NULL;
}
if (platform.fd != -1)
{
close(platform.fd);
platform.fd = -1;
}
// Close surface, context and display
if (platform.device != EGL_NO_DISPLAY)
{
if (platform.surface != EGL_NO_SURFACE)
{
eglDestroySurface(platform.device, platform.surface);
platform.surface = EGL_NO_SURFACE;
}
if (platform.context != EGL_NO_CONTEXT)
{
eglDestroyContext(platform.device, platform.context);
platform.context = EGL_NO_CONTEXT;
}
eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY;
}
// Wait for mouse and gamepad threads to finish before closing
// NOTE: Those threads should already have finished at this point
// because they are controlled by CORE.Window.shouldClose variable
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
// Close the evdev keyboard
if (platform.keyboardFd != -1)
{
close(platform.keyboardFd);
platform.keyboardFd = -1;
}
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
{
if (platform.eventWorker[i].threadId)
{
pthread_join(platform.eventWorker[i].threadId, NULL);
}
}
if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
//-------------------------------------------------------------- //--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
@ -412,36 +322,6 @@ bool WindowShouldClose(void)
else return true; else return true;
} }
// Check if window is currently hidden
bool IsWindowHidden(void)
{
return false;
}
// Check if window has been minimized
bool IsWindowMinimized(void)
{
return false;
}
// Check if window has been maximized
bool IsWindowMaximized(void)
{
return false;
}
// Check if window has the focus
bool IsWindowFocused(void)
{
return true;
}
// Check if window has been resizedLastFrame
bool IsWindowResized(void)
{
return false;
}
// Toggle fullscreen mode // Toggle fullscreen mode
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
@ -830,28 +710,9 @@ void PollInputEvents(void)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize display device and framebuffer // Initialize platform: graphics, inputs and more
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size static int InitPlatform(void)
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
{ {
CORE.Window.screen.width = width; // User desired width
CORE.Window.screen.height = height; // User desired height
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
// Set the window minimum and maximum default values to 0
CORE.Window.screenMin.width = 0;
CORE.Window.screenMin.height = 0;
CORE.Window.screenMax.width = 0;
CORE.Window.screenMax.height = 0;
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
platform.fd = -1; platform.fd = -1;
platform.connector = NULL; platform.connector = NULL;
platform.modeIndex = -1; platform.modeIndex = -1;
@ -860,6 +721,9 @@ static bool InitGraphicsDevice(int width, int height)
platform.gbmSurface = NULL; platform.gbmSurface = NULL;
platform.prevBO = NULL; platform.prevBO = NULL;
platform.prevFB = 0; platform.prevFB = 0;
CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM) #if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR); platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
@ -883,14 +747,14 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.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 -1;
} }
drmModeRes *res = drmModeGetResources(platform.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");
return false; return -1;
} }
TRACELOG(LOG_TRACE, "DISPLAY: Connectors found: %i", res->count_connectors); TRACELOG(LOG_TRACE, "DISPLAY: Connectors found: %i", res->count_connectors);
@ -919,7 +783,7 @@ static bool InitGraphicsDevice(int width, int height)
{ {
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 -1;
} }
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id); drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
@ -927,7 +791,7 @@ static bool InitGraphicsDevice(int width, int height)
{ {
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder"); TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
drmModeFreeResources(res); drmModeFreeResources(res);
return false; return -1;
} }
platform.crtc = drmModeGetCrtc(platform.fd, enc->crtc_id); platform.crtc = drmModeGetCrtc(platform.fd, enc->crtc_id);
@ -936,7 +800,7 @@ static bool InitGraphicsDevice(int width, int height)
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc"); TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
drmModeFreeEncoder(enc); drmModeFreeEncoder(enc);
drmModeFreeResources(res); drmModeFreeResources(res);
return false; return -1;
} }
// If InitWindow should use the current mode find it in the connector's mode list // If InitWindow should use the current mode find it in the connector's mode list
@ -951,7 +815,7 @@ static bool InitGraphicsDevice(int width, int height)
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found"); TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
drmModeFreeEncoder(enc); drmModeFreeEncoder(enc);
drmModeFreeResources(res); drmModeFreeResources(res);
return false; return -1;
} }
CORE.Window.screen.width = CORE.Window.display.width; CORE.Window.screen.width = CORE.Window.display.width;
@ -979,7 +843,7 @@ static bool InitGraphicsDevice(int width, int height)
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);
drmModeFreeResources(res); drmModeFreeResources(res);
return false; return -1;
} }
CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay; CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay;
@ -1004,7 +868,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!platform.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 -1;
} }
platform.gbmSurface = gbm_surface_create(platform.gbmDevice, platform.connector->modes[platform.modeIndex].hdisplay, platform.gbmSurface = gbm_surface_create(platform.gbmDevice, platform.connector->modes[platform.modeIndex].hdisplay,
@ -1012,7 +876,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!platform.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 -1;
} }
EGLint samples = 0; EGLint samples = 0;
@ -1052,7 +916,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.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 -1;
} }
// Initialize the EGL device connection // Initialize the EGL device connection
@ -1060,13 +924,13 @@ static bool InitGraphicsDevice(int width, int height)
{ {
// 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 -1;
} }
if (!eglChooseConfig(platform.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 -1;
} }
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs); TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
@ -1075,7 +939,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!configs) if (!configs)
{ {
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs"); TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
return false; return -1;
} }
EGLint matchingNumConfigs = 0; EGLint matchingNumConfigs = 0;
@ -1083,7 +947,7 @@ static bool InitGraphicsDevice(int width, int height)
{ {
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);
return false; return -1;
} }
TRACELOG(LOG_TRACE, "DISPLAY: EGL matching configs available: %d", matchingNumConfigs); TRACELOG(LOG_TRACE, "DISPLAY: EGL matching configs available: %d", matchingNumConfigs);
@ -1113,7 +977,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!found) if (!found)
{ {
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable EGL config"); TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable EGL config");
return false; return -1;
} }
// Set rendering API // Set rendering API
@ -1124,7 +988,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.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 -1;
} }
// Create an EGL window surface // Create an EGL window surface
@ -1133,7 +997,7 @@ static bool InitGraphicsDevice(int width, int height)
if (EGL_NO_SURFACE == platform.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 -1;
} }
// At this point we need to manage render size vs screen size // At this point we need to manage render size vs screen size
@ -1149,7 +1013,7 @@ static bool InitGraphicsDevice(int width, int height)
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.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 -1;
} }
else else
{ {
@ -1169,19 +1033,125 @@ static bool InitGraphicsDevice(int width, int height)
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(eglGetProcAddress); rlLoadExtensions(eglGetProcAddress);
// Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
return true; // Set some default window flags
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // false
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
// Initialize hi-res timer
InitTimer();
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
// Initialize raw input system
InitEvdevInput(); // Evdev inputs initialization
InitGamepad(); // Gamepad init
InitKeyboard(); // Keyboard init (stdin)
return 0;
} }
// Close platform
static void ClosePlatform(void)
{
if (platform.prevFB)
{
drmModeRmFB(platform.fd, platform.prevFB);
platform.prevFB = 0;
}
if (platform.prevBO)
{
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
platform.prevBO = NULL;
}
if (platform.gbmSurface)
{
gbm_surface_destroy(platform.gbmSurface);
platform.gbmSurface = NULL;
}
if (platform.gbmDevice)
{
gbm_device_destroy(platform.gbmDevice);
platform.gbmDevice = NULL;
}
if (platform.crtc)
{
if (platform.connector)
{
drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
drmModeFreeConnector(platform.connector);
platform.connector = NULL;
}
drmModeFreeCrtc(platform.crtc);
platform.crtc = NULL;
}
if (platform.fd != -1)
{
close(platform.fd);
platform.fd = -1;
}
// Close surface, context and display
if (platform.device != EGL_NO_DISPLAY)
{
if (platform.surface != EGL_NO_SURFACE)
{
eglDestroySurface(platform.device, platform.surface);
platform.surface = EGL_NO_SURFACE;
}
if (platform.context != EGL_NO_CONTEXT)
{
eglDestroyContext(platform.device, platform.context);
platform.context = EGL_NO_CONTEXT;
}
eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY;
}
// Wait for mouse and gamepad threads to finish before closing
// NOTE: Those threads should already have finished at this point
// because they are controlled by CORE.Window.shouldClose variable
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
// Close the evdev keyboard
if (platform.keyboardFd != -1)
{
close(platform.keyboardFd);
platform.keyboardFd = -1;
}
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
{
if (platform.eventWorker[i].threadId)
{
pthread_join(platform.eventWorker[i].threadId, NULL);
}
}
if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
}
// Initialize Keyboard system (using standard input) // Initialize Keyboard system (using standard input)
static void InitKeyboard(void) static void InitKeyboard(void)
{ {

View File

@ -73,7 +73,8 @@ static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
static bool InitGraphicsDevice(void); // Initialize graphics device
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Declaration // Module Functions Declaration
@ -128,8 +129,11 @@ void InitWindow(int width, int height, const char *title)
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f }; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Window.eventWaiting = false; CORE.Window.eventWaiting = false;
// TODO: Platform specific init window
//--------------------------------------------------------------
CORE.Window.screen.width = width; CORE.Window.screen.width = width;
CORE.Window.screen.height = height; CORE.Window.screen.height = height;
CORE.Window.currentFbo.width = width; CORE.Window.currentFbo.width = width;
@ -139,17 +143,15 @@ void InitWindow(int width, int height, const char *title)
// NOTE: returns true if window and graphic device has been initialized successfully // NOTE: returns true if window and graphic device has been initialized successfully
CORE.Window.ready = InitGraphicsDevice(width, height); CORE.Window.ready = InitGraphicsDevice(width, height);
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
// Initialize hi-res timer
InitTimer(); // Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize random seed // Setup default viewport
SetRandomSeed((unsigned int)time(NULL)); // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font // Load default font
@ -193,10 +195,8 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
#endif #endif
// TODO: Platform specific init window // Initialize random seed
//-------------------------------------------------------------- SetRandomSeed((unsigned int)time(NULL));
// ...
//--------------------------------------------------------------
TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Application initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Application initialized successfully");
} }
@ -239,36 +239,6 @@ bool WindowShouldClose(void)
else return true; else return true;
} }
// Check if window is currently hidden
bool IsWindowHidden(void)
{
return false;
}
// Check if window has been minimized
bool IsWindowMinimized(void)
{
return false;
}
// Check if window has been maximized
bool IsWindowMaximized(void)
{
return false;
}
// Check if window has the focus
bool IsWindowFocused(void)
{
return platform.appEnabled;
}
// Check if window has been resizedLastFrame
bool IsWindowResized(void)
{
return false;
}
// Toggle fullscreen mode // Toggle fullscreen mode
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
@ -627,25 +597,9 @@ void PollInputEvents(void)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize display device and framebuffer // Initialize platform: graphics, inputs and more
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size static int InitPlatform(void)
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
{ {
CORE.Window.screen.width = width; // User desired width
CORE.Window.screen.height = height; // User desired height
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
// Set the screen minimum and maximum default values to 0
CORE.Window.screenMin.width = 0;
CORE.Window.screenMin.height = 0;
CORE.Window.screenMax.width = 0;
CORE.Window.screenMax.height = 0;
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
CORE.Window.fullscreen = true; CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE; CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
@ -707,7 +661,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.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 -1;
} }
// Create an EGL window surface // Create an EGL window surface
@ -736,7 +690,7 @@ static bool InitGraphicsDevice(int width, int height)
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.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 -1;
} }
else else
{ {
@ -756,19 +710,24 @@ static bool InitGraphicsDevice(int width, int height)
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(eglGetProcAddress); rlLoadExtensions(eglGetProcAddress);
// Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
CORE.Window.ready = true; CORE.Window.ready = true;
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); // Initialize hi-res timer
InitTimer();
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
return true; return 0;
}
// Close platform
static void ClosePlatform(void)
{
// TODO: De-initialize graphics, inputs and more
} }
// EOF // EOF

View File

@ -87,17 +87,18 @@ static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
static void ClosePlatform(void); // Close platform
// Error callback event // Error callback event
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
// Window callbacks events // Window callbacks events
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowMaximizeCallback(GLFWwindow *window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized static void WindowMaximizeCallback(GLFWwindow *window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
// Input callbacks events // Input callbacks events
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
@ -107,11 +108,12 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y);
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
// Emscripten callback events // Emscripten window callback events
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData); static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData); static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData); static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
// Emscripten input callback events
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
@ -160,33 +162,32 @@ void InitWindow(int width, int height, const char *title)
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)"); TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
#endif #endif
// NOTE: Keep internal pointer to input title string (no copy) // Initialize window data
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
CORE.Window.eventWaiting = false;
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
// Initialize global input state // Initialize global input state
memset(&CORE.Input, 0, sizeof(CORE.Input)); memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
CORE.Input.Keyboard.exitKey = KEY_ESCAPE; CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
CORE.Input.Mouse.scale = (Vector2){1.0f, 1.0f}; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
CORE.Window.eventWaiting = false;
// Initialize graphics device (display device and OpenGL context) // Initialize platform
// NOTE: returns true if window and graphic device has been initialized successfully //--------------------------------------------------------------
CORE.Window.ready = InitGraphicsDevice(width, height); InitPlatform();
//--------------------------------------------------------------
// If graphic device is no properly initialized, we end program // Initialize OpenGL context (states and resources)
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; } // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize hi-res timer // Setup default viewport
InitTimer(); // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font // Load default font
@ -230,37 +231,8 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
#endif #endif
// Platform specific init window // Initialize random seed
//-------------------------------------------------------------- SetRandomSeed((unsigned int)time(NULL));
// Setup callback functions for the DOM events
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
// emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
// Trigger this once to get initial window sizing
EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
// Support keyboard events -> Not used, GLFW.JS takes care of that
// emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
// emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
// Support mouse events
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
// Support touch events
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
// Support gamepad events (not provided by GLFW3 on emscripten)
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
//--------------------------------------------------------------
TRACELOG(LOG_INFO, "PLATFORM: WEB: Application initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: WEB: Application initialized successfully");
} }
@ -283,10 +255,9 @@ void CloseWindow(void)
rlglClose(); // De-init rlgl rlglClose(); // De-init rlgl
// Platform specific close window // De-initialize platform
//-------------------------------------------------------------- //--------------------------------------------------------------
glfwDestroyWindow(platform.handle); ClosePlatform();
glfwTerminate();
//-------------------------------------------------------------- //--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
@ -309,36 +280,6 @@ bool WindowShouldClose(void)
return false; return false;
} }
// Check if window is currently hidden
bool IsWindowHidden(void)
{
return false;
}
// Check if window has been minimized
bool IsWindowMinimized(void)
{
return false;
}
// Check if window has been maximized
bool IsWindowMaximized(void)
{
return false;
}
// Check if window has the focus
bool IsWindowFocused(void)
{
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
}
// Check if window has been resizedLastFrame
bool IsWindowResized(void)
{
return CORE.Window.resizedLastFrame;
}
// Toggle fullscreen mode // Toggle fullscreen mode
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
@ -718,7 +659,34 @@ void SetMousePosition(int x, int y)
// Set mouse cursor // Set mouse cursor
void SetMouseCursor(int cursor) void SetMouseCursor(int cursor)
{ {
TRACELOG(LOG_INFO, "SetMouseCursor not implemented in rcore_web.c"); const char *cursorName;
switch (cursor)
{
case MOUSE_CURSOR_IBEAM: cursorName = "text"; break;
case MOUSE_CURSOR_CROSSHAIR: cursorName = "crosshair"; break;
case MOUSE_CURSOR_POINTING_HAND: cursorName = "pointer"; break;
case MOUSE_CURSOR_RESIZE_EW: cursorName = "ew-resize"; break;
case MOUSE_CURSOR_RESIZE_NS: cursorName = "ns-resize"; break;
case MOUSE_CURSOR_RESIZE_NWSE: cursorName = "nwse-resize"; break;
case MOUSE_CURSOR_RESIZE_NESW: cursorName = "nesw-resize"; break;
case MOUSE_CURSOR_RESIZE_ALL: cursorName = "move"; break;
case MOUSE_CURSOR_NOT_ALLOWED: cursorName = "not-allowed"; break;
case MOUSE_CURSOR_ARROW: // can't find a name specifically for arrow cursor
case MOUSE_CURSOR_DEFAULT:
{
cursorName = "default";
} break;
default:
{
TRACELOG(LOG_WARNING, "Cursor value out of bound (%d). Setting to default", cursor);
cursorName = "default";
} break;
}
// Set the cursor element on the CSS
EM_ASM({document.body.style.cursor = UTF8ToString($0);}, cursorName);
} }
// Register all input events // Register all input events
@ -842,43 +810,14 @@ void PollInputEvents(void)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize display device and framebuffer // Initialize platform: graphics, inputs and more
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size static int InitPlatform(void)
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
{ {
CORE.Window.screen.width = width; // User desired width
CORE.Window.screen.height = height; // User desired height
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
// Set the screen minimum and maximum default values to 0
CORE.Window.screenMin.width = 0;
CORE.Window.screenMin.height = 0;
CORE.Window.screenMax.width = 0;
CORE.Window.screenMax.height = 0;
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
glfwSetErrorCallback(ErrorCallback); glfwSetErrorCallback(ErrorCallback);
/*
// TODO: Setup GLFW custom allocators to match raylib ones
const GLFWallocator allocator = {
.allocate = MemAlloc,
.deallocate = MemFree,
.reallocate = MemRealloc,
.user = NULL
};
glfwInitAllocator(&allocator); // Initialize GLFW internal global state
*/ int result = glfwInit();
if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }
if (!glfwInit())
{
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW");
return false;
}
glfwDefaultWindowHints(); // Set default windows hints glfwDefaultWindowHints(); // Set default windows hints
// glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits // glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
@ -1044,7 +983,7 @@ static bool InitGraphicsDevice(int width, int height)
{ {
glfwTerminate(); glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window"); TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return false; return -1;
} }
// WARNING: glfwCreateWindow() title doesn't work with emscripten // WARNING: glfwCreateWindow() title doesn't work with emscripten
@ -1065,6 +1004,12 @@ static bool InitGraphicsDevice(int width, int height)
glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback); glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);
glfwMakeContextCurrent(platform.handle); glfwMakeContextCurrent(platform.handle);
// Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(glfwGetProcAddress);
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
// 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
@ -1083,22 +1028,56 @@ static bool InitGraphicsDevice(int width, int height)
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
// Load OpenGL extensions // Initialize hi-res timer
// NOTE: GL procedures address loader is required to load extensions InitTimer();
rlLoadExtensions(glfwGetProcAddress);
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
// Setup callback functions for the DOM events
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
// Initialize OpenGL context (states and resources) // WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); // emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
// Setup default viewport // Trigger this once to get initial window sizing
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); // Support keyboard events -> Not used, GLFW.JS takes care of that
// emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
// emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
return true; // Support mouse events
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
// Support touch events
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
// Support gamepad events (not provided by GLFW3 on emscripten)
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
return 0;
}
// Close platform
static void ClosePlatform(void)
{
glfwDestroyWindow(platform.handle);
glfwTerminate();
} }
// GLFW3 Error Callback, runs on GLFW3 error // GLFW3 Error Callback, runs on GLFW3 error
@ -1147,7 +1126,7 @@ static void WindowIconifyCallback(GLFWwindow *window, int iconified)
// GLFW3 Window Maximize Callback, runs when window is maximized // GLFW3 Window Maximize Callback, runs when window is maximized
static void WindowMaximizeCallback(GLFWwindow *window, int maximized) static void WindowMaximizeCallback(GLFWwindow *window, int maximized)
{ {
// TODO.
} }
// GLFW3 WindowFocus Callback, runs when window get/lose focus // GLFW3 WindowFocus Callback, runs when window get/lose focus
@ -1185,7 +1164,6 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
} }
} }
// GLFW3 Keyboard Callback, runs on key pressed // GLFW3 Keyboard Callback, runs on key pressed
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
{ {
@ -1364,11 +1342,10 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
// GLFW3 CursorEnter Callback, when cursor enters the window // GLFW3 CursorEnter Callback, when cursor enters the window
static void CursorEnterCallback(GLFWwindow *window, int enter) static void CursorEnterCallback(GLFWwindow *window, int enter)
{ {
if (enter == true) CORE.Input.Mouse.cursorOnScreen = true; if (enter) CORE.Input.Mouse.cursorOnScreen = true;
else CORE.Input.Mouse.cursorOnScreen = false; else CORE.Input.Mouse.cursorOnScreen = false;
} }
// Register fullscreen change events // Register fullscreen change events
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData) static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
{ {

View File

@ -213,7 +213,7 @@
#define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size)) #define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size))
#define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr)) #define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr))
#define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()] #include "external/stb_image_resize2.h" // Required for: stbir_resize_uint8_linear() [ImageResize()]
#if defined(SUPPORT_FILEFORMAT_SVG) #if defined(SUPPORT_FILEFORMAT_SVG)
#define NANOSVG_IMPLEMENTATION // Expands implementation #define NANOSVG_IMPLEMENTATION // Expands implementation
@ -1624,10 +1624,10 @@ void ImageResize(Image *image, int newWidth, int newHeight)
switch (image->format) switch (image->format)
{ {
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 1); break; case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)1); break;
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 2); break; case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)2); break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 3); break; case PIXELFORMAT_UNCOMPRESSED_R8G8B8: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)3); break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 4); break; case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)4); break;
default: break; default: break;
} }
@ -1643,7 +1643,7 @@ void ImageResize(Image *image, int newWidth, int newHeight)
Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color)); Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
// NOTE: Color data is cast to (unsigned char *), there shouldn't been any problem... // NOTE: Color data is cast to (unsigned char *), there shouldn't been any problem...
stbir_resize_uint8((unsigned char *)pixels, image->width, image->height, 0, (unsigned char *)output, newWidth, newHeight, 0, 4); stbir_resize_uint8_linear((unsigned char *)pixels, image->width, image->height, 0, (unsigned char *)output, newWidth, newHeight, 0, (stbir_pixel_layout)4);
int format = image->format; int format = image->format;