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 |
| 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.lean | 4.5 | [Lean4](https://lean-lang.org/) | BSD-3-Clause | https://github.com/KislyjKisel/Raylib.lean |
### 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.

View File

@ -1,7 +1,7 @@
const std = @import("std");
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 {
raylib.build(b);
}

View File

@ -1,7 +1,7 @@
const std = @import("std");
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 {
if (target.getOsTag() == .emscripten) {
@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, .{});
var iter = dir.iterate();
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 name = entry.name[0..extension_idx];
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,
.optimize = optimize,
});
exe.addCSourceFile(path, &[_][]const u8{});
exe.addCSourceFile(.{ .file = .{ .path = path }, .flags = &.{} });
exe.linkLibC();
exe.addObjectFile(switch (target.getOsTag()) {
.windows => "../src/zig-out/lib/raylib.lib",
.linux => "../src/zig-out/lib/libraylib.a",
.macos => "../src/zig-out/lib/libraylib.a",
.emscripten => "../src/zig-out/lib/libraylib.a",
.windows => .{ .path = "../zig-out/lib/raylib.lib" },
.linux => .{ .path = "../zig-out/lib/libraylib.a" },
.macos => .{ .path = "../zig-out/lib/libraylib.a" },
.emscripten => .{ .path = "../zig-out/lib/libraylib.a" },
else => @panic("Unsupported OS"),
});
exe.addIncludePath("../src");
exe.addIncludePath("../src/external");
exe.addIncludePath("../src/external/glfw/include");
exe.addIncludePath(.{ .path = "../src" });
exe.addIncludePath(.{ .path = "../src/external" });
exe.addIncludePath(.{ .path = "../src/external/glfw/include" });
switch (target.getOsTag()) {
.windows => {
exe.linkSystemLibrary("winmm");
exe.linkSystemLibrary("gdi32");
exe.linkSystemLibrary("opengl32");
exe.addIncludePath("external/glfw/deps/mingw");
exe.addIncludePath(.{ .path = "external/glfw/deps/mingw" });
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);
var run = b.addRunArtifact(exe);
run.cwd = module;
b.step(name, name).dependOn(&run.step);
all.dependOn(&exe.step);
const install_cmd = b.addInstallArtifact(exe, .{});
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(&install_cmd.step);
const run_step = b.step(name, name);
run_step.dependOn(&run_cmd.step);
all.dependOn(&install_cmd.step);
}
return all;
}

View File

@ -1,6 +1,6 @@
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 {
const raylib_flags = &[_][]const u8{
"-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
void UpdateSound(Sound sound, const void *data, int sampleCount)
void UpdateSound(Sound sound, const void *data, int frameCount)
{
if (sound.stream.buffer != NULL)
{
StopAudioBuffer(sound.stream.buffer);
// 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 CloseWindow(void)
//bool WindowShouldClose(void)
//bool IsWindowHidden(void)
//bool IsWindowMinimized(void)
//bool IsWindowMaximized(void)
//bool IsWindowFocused(void)
//bool IsWindowResized(void)
//void ToggleFullscreen(void)
//void ToggleBorderlessWindowed(void)
//void MaximizeWindow(void)
//void MinimizeWindow(void)
//void RestoreWindow(void)
//void ToggleBorderlessWindowed(void)
//void SetWindowState(unsigned int flags)
//void ClearWindowState(unsigned int flags)
//void SetWindowIcon(Image image)
//void SetWindowIcons(Image *images, int count)
//void SetWindowTitle(const char *title)
@ -345,25 +342,27 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
//void SetWindowOpacity(float opacity)
//void SetWindowFocused(void)
//void *GetWindowHandle(void)
//Vector2 GetWindowPosition(void)
//Vector2 GetWindowScaleDPI(void)
//int GetMonitorCount(void)
//int GetCurrentMonitor(void)
//Vector2 GetMonitorPosition(int monitor)
//int GetMonitorWidth(int monitor)
//int GetMonitorHeight(int monitor)
//int GetMonitorPhysicalWidth(int monitor)
//int GetMonitorPhysicalHeight(int monitor)
//int GetMonitorRefreshRate(int monitor)
//Vector2 GetMonitorPosition(int monitor)
//const char *GetMonitorName(int monitor)
//Vector2 GetWindowPosition(void)
//Vector2 GetWindowScaleDPI(void)
//void SetClipboardText(const char *text)
//const char *GetClipboardText(void)
//void ShowCursor(void)
//void HideCursor(void)
//void EnableCursor(void)
//void DisableCursor(void)
// Check if window has been initialized successfully
bool IsWindowReady(void)
{
@ -376,6 +375,36 @@ bool IsWindowFullscreen(void)
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
bool IsWindowState(unsigned int flag)
{
@ -394,13 +423,13 @@ int GetScreenHeight(void)
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)
{
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)
{
return CORE.Window.render.height;
@ -2331,15 +2360,15 @@ int GetTouchPointCount(void)
//----------------------------------------------------------------------------------
// 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
void InitTimer(void)
{
// 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.
// 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 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.
// 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.
#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)
#endif
@ -2783,7 +2812,7 @@ static void RecordAutomationEvent(unsigned int frame)
// INPUT_GAMEPAD_CONNECT
/*
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
}
@ -2792,7 +2821,7 @@ static void RecordAutomationEvent(unsigned int frame)
// INPUT_GAMEPAD_DISCONNECT
/*
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
}

View File

@ -82,7 +82,8 @@ static PlatformData platform = { 0 }; // Platform specific data
//----------------------------------------------------------------------------------
// 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 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)");
#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;
// 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.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Window.eventWaiting = false;
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height;
// Platform specific init window
// Initialize platform
//--------------------------------------------------------------
// 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;
}
}
InitPlatform();
//--------------------------------------------------------------
}
@ -272,28 +215,9 @@ void CloseWindow(void)
timeEndPeriod(1); // Restore time period
#endif
// Platform specific close window
// De-initialize platform
//--------------------------------------------------------------
// 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;
}
ClosePlatform();
//--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION)
@ -311,36 +235,6 @@ bool WindowShouldClose(void)
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
void ToggleFullscreen(void)
{
@ -713,25 +607,108 @@ void PollInputEvents(void)
// 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
// 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
// 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.flags |= FLAG_FULLSCREEN_MODE;
@ -771,7 +748,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.device == EGL_NO_DISPLAY)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return false;
return -1;
}
// 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.
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return false;
return -1;
}
// Get an appropriate EGL framebuffer configuration
@ -793,7 +770,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.context == EGL_NO_CONTEXT)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
return false;
return -1;
}
// 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)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
return false;
return -1;
}
else
{
@ -842,19 +819,11 @@ static bool InitGraphicsDevice(int width, int height)
// NOTE: GL procedures address loader is required to load extensions
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;
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
return true;
return 0;
}
// ANDROID: Process activity lifecycle commands
@ -897,25 +866,50 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
CORE.Window.display.height = ANativeWindow_getHeight(platform.app->window);
// 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
InitTimer();
// Initialize random seed
srand((unsigned int)time(NULL));
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font
// WARNING: External function: Module required: rtext
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)
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
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// TODO: GPU assets reload in case of lost focus (lost context)
// 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:
{
platform.appEnabled = true;
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
//ResumeMusicStream();
} break;
case APP_CMD_PAUSE: break;
case APP_CMD_LOST_FOCUS:
{
platform.appEnabled = false;
CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
//PauseMusicStream();
} break;
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.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
@ -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;
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
CORE.Input.Mouse.currentPosition = CORE.Input.Touch.position[0];
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
*
* PLATFORM: DESKTOP
* PLATFORM: DESKTOP: GLFW
* - Windows (Win32, Win64)
* - Linux (X11/Wayland desktop mode)
* - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
@ -111,7 +111,8 @@ static PlatformData platform = { 0 }; // Platform specific data
//----------------------------------------------------------------------------------
// 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
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)");
#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;
// 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.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Window.eventWaiting = false;
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
// Initialize graphics device
// NOTE: returns true if window and graphic device has been initialized successfully
CORE.Window.ready = InitGraphicsDevice(width, height);
// Initialize platform
//--------------------------------------------------------------
InitPlatform();
//--------------------------------------------------------------
// 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 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 hi-res timer
InitTimer();
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
// Setup default viewport
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -246,6 +245,9 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0;
#endif
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: Application initialized successfully");
}
@ -267,14 +269,9 @@ void CloseWindow(void)
rlglClose(); // De-init rlgl
// Platform specific close window
// De-initialize platform
//--------------------------------------------------------------
glfwDestroyWindow(platform.handle);
glfwTerminate();
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
timeEndPeriod(1); // Restore time period
#endif
ClosePlatform();
//--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION)
@ -304,36 +301,6 @@ bool WindowShouldClose(void)
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
void ToggleFullscreen(void)
{
@ -1389,25 +1356,9 @@ void PollInputEvents(void)
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
// Initialize platform: graphics, inputs and more
static int InitPlatform(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)
glfwSetErrorCallback(ErrorCallback);
/*
// TODO: Setup GLFW custom allocators to match raylib ones
@ -1420,15 +1371,13 @@ static bool InitGraphicsDevice(int width, int height)
glfwInitAllocator(&allocator);
*/
#if defined(__APPLE__)
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
#endif
if (!glfwInit())
{
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW");
return false;
}
// Initialize GLFW internal global state
int result = glfwInit();
if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }
glfwDefaultWindowHints(); // Set default windows hints
//glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
@ -1550,7 +1499,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!monitor)
{
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
return false;
return -1;
}
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
@ -1639,7 +1588,7 @@ static bool InitGraphicsDevice(int width, int height)
{
glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return false;
return -1;
}
// Set window callback events
@ -1705,22 +1654,37 @@ static bool InitGraphicsDevice(int width, int height)
// Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions
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();
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
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
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;
}

View File

@ -140,21 +140,22 @@ static PlatformData platform = { 0 }; // Platform specific data
//----------------------------------------------------------------------------------
// 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 RestoreKeyboard(void); // Restore keyboard system
static void InitKeyboard(void); // Initialize raw keyboard system
static void RestoreKeyboard(void); // Restore keyboard system
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
static void ProcessKeyboard(void); // Process keyboard events
static void ProcessKeyboard(void); // Process keyboard events
#endif
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 PollKeyboardEvents(void); // Process evdev keyboard events
static void *EventThread(void *arg); // Input device events reading thread
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 PollKeyboardEvents(void); // Process evdev keyboard events
static void *EventThread(void *arg); // Input device events reading thread
static void InitGamepad(void); // Initialize raw gamepad input
static void *GamepadThread(void *arg); // Mouse reading thread
static void InitGamepad(void); // Initialize raw gamepad input
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 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)");
#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;
// 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.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.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Window.eventWaiting = false;
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
// Initialize graphics device (display device and OpenGL context)
// NOTE: returns true if window and graphic device has been initialized successfully
CORE.Window.ready = InitGraphicsDevice(width, height);
// Initialize platform
//--------------------------------------------------------------
InitPlatform();
//--------------------------------------------------------------
// 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 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 hi-res timer
InitTimer();
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
// Setup default viewport
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -274,13 +273,8 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0;
#endif
// Platform specific init window
//--------------------------------------------------------------
// Initialize raw input system
InitEvdevInput(); // Evdev inputs initialization
InitGamepad(); // Gamepad init
InitKeyboard(); // Keyboard init (stdin)
//--------------------------------------------------------------
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "PLATFORM: DRM: Application initialized successfully");
}
@ -307,93 +301,9 @@ void CloseWindow(void)
timeEndPeriod(1); // Restore time period
#endif
// Platform specific close window
// De-initialize platform
//--------------------------------------------------------------
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);
ClosePlatform();
//--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION)
@ -412,36 +322,6 @@ bool WindowShouldClose(void)
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
void ToggleFullscreen(void)
{
@ -830,28 +710,9 @@ void PollInputEvents(void)
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
// Initialize platform: graphics, inputs and more
static int InitPlatform(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 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.connector = NULL;
platform.modeIndex = -1;
@ -861,6 +722,9 @@ static bool InitGraphicsDevice(int width, int height)
platform.prevBO = NULL;
platform.prevFB = 0;
CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
#else
@ -883,14 +747,14 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.fd == -1)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card");
return false;
return -1;
}
drmModeRes *res = drmModeGetResources(platform.fd);
if (!res)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
return false;
return -1;
}
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");
drmModeFreeResources(res);
return false;
return -1;
}
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");
drmModeFreeResources(res);
return false;
return -1;
}
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");
drmModeFreeEncoder(enc);
drmModeFreeResources(res);
return false;
return -1;
}
// 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");
drmModeFreeEncoder(enc);
drmModeFreeResources(res);
return false;
return -1;
}
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");
drmModeFreeEncoder(enc);
drmModeFreeResources(res);
return false;
return -1;
}
CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay;
@ -1004,7 +868,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!platform.gbmDevice)
{
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,
@ -1012,7 +876,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!platform.gbmSurface)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM surface");
return false;
return -1;
}
EGLint samples = 0;
@ -1052,7 +916,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.device == EGL_NO_DISPLAY)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return false;
return -1;
}
// 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.
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return false;
return -1;
}
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
{
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);
@ -1075,7 +939,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!configs)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
return false;
return -1;
}
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());
free(configs);
return false;
return -1;
}
TRACELOG(LOG_TRACE, "DISPLAY: EGL matching configs available: %d", matchingNumConfigs);
@ -1113,7 +977,7 @@ static bool InitGraphicsDevice(int width, int height)
if (!found)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable EGL config");
return false;
return -1;
}
// Set rendering API
@ -1124,7 +988,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.context == EGL_NO_CONTEXT)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
return false;
return -1;
}
// Create an EGL window surface
@ -1133,7 +997,7 @@ static bool InitGraphicsDevice(int width, int height)
if (EGL_NO_SURFACE == platform.surface)
{
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
@ -1149,7 +1013,7 @@ static bool InitGraphicsDevice(int width, int height)
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");
return false;
return -1;
}
else
{
@ -1169,19 +1033,125 @@ static bool InitGraphicsDevice(int width, int height)
// NOTE: GL procedures address loader is required to load extensions
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();
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);
// 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)
static void InitKeyboard(void)
{

View File

@ -73,7 +73,8 @@ static PlatformData platform = { 0 }; // Platform specific data
//----------------------------------------------------------------------------------
// 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
@ -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.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Window.eventWaiting = false;
// TODO: Platform specific init window
//--------------------------------------------------------------
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
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
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 random seed
SetRandomSeed((unsigned int)time(NULL));
// 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 base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
// 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 defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -193,10 +195,8 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0;
#endif
// TODO: Platform specific init window
//--------------------------------------------------------------
// ...
//--------------------------------------------------------------
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Application initialized successfully");
}
@ -239,36 +239,6 @@ bool WindowShouldClose(void)
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
void ToggleFullscreen(void)
{
@ -627,25 +597,9 @@ void PollInputEvents(void)
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
// Initialize platform: graphics, inputs and more
static int InitPlatform(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.flags |= FLAG_FULLSCREEN_MODE;
@ -707,7 +661,7 @@ static bool InitGraphicsDevice(int width, int height)
if (platform.context == EGL_NO_CONTEXT)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
return false;
return -1;
}
// 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)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
return false;
return -1;
}
else
{
@ -756,19 +710,24 @@ static bool InitGraphicsDevice(int width, int height)
// NOTE: GL procedures address loader is required to load extensions
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;
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
// 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; }
return true;
// Initialize hi-res timer
InitTimer();
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
return 0;
}
// Close platform
static void ClosePlatform(void)
{
// TODO: De-initialize graphics, inputs and more
}
// EOF

View File

@ -87,17 +87,18 @@ static PlatformData platform = { 0 }; // Platform specific data
//----------------------------------------------------------------------------------
// 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
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
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 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 WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
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 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 WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
// Input callbacks events
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 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 EmscriptenWindowResizedCallback(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 EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, 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)");
#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;
// 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.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.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Window.eventWaiting = false;
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
// Initialize graphics device (display device and OpenGL context)
// NOTE: returns true if window and graphic device has been initialized successfully
CORE.Window.ready = InitGraphicsDevice(width, height);
// Initialize platform
//--------------------------------------------------------------
InitPlatform();
//--------------------------------------------------------------
// 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 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 hi-res timer
InitTimer();
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
// 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 defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -230,37 +231,8 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0;
#endif
// Platform specific init window
//--------------------------------------------------------------
// 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);
//--------------------------------------------------------------
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "PLATFORM: WEB: Application initialized successfully");
}
@ -283,10 +255,9 @@ void CloseWindow(void)
rlglClose(); // De-init rlgl
// Platform specific close window
// De-initialize platform
//--------------------------------------------------------------
glfwDestroyWindow(platform.handle);
glfwTerminate();
ClosePlatform();
//--------------------------------------------------------------
#if defined(SUPPORT_EVENTS_AUTOMATION)
@ -309,36 +280,6 @@ bool WindowShouldClose(void)
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
void ToggleFullscreen(void)
{
@ -718,7 +659,34 @@ void SetMousePosition(int x, int y)
// Set mouse 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
@ -842,43 +810,14 @@ void PollInputEvents(void)
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
// If width or height are 0, default display size will be used for framebuffer size
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
// Initialize platform: graphics, inputs and more
static int InitPlatform(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)
glfwSetErrorCallback(ErrorCallback);
/*
// TODO: Setup GLFW custom allocators to match raylib ones
const GLFWallocator allocator = {
.allocate = MemAlloc,
.deallocate = MemFree,
.reallocate = MemRealloc,
.user = NULL
};
glfwInitAllocator(&allocator);
*/
if (!glfwInit())
{
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW");
return false;
}
// Initialize GLFW internal global state
int result = glfwInit();
if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }
glfwDefaultWindowHints(); // Set default windows hints
// glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
@ -1044,7 +983,7 @@ static bool InitGraphicsDevice(int width, int height)
{
glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return false;
return -1;
}
// WARNING: glfwCreateWindow() title doesn't work with emscripten
@ -1066,6 +1005,12 @@ static bool InitGraphicsDevice(int width, int height)
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)
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
// to be activated on web platforms since VSync is enforced there.
@ -1084,21 +1029,55 @@ static bool InitGraphicsDevice(int width, int 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);
// Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(glfwGetProcAddress);
CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
// 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);
// 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);
// 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
InitTimer();
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
// Initialize base path for storage
CORE.Storage.basePath = GetWorkingDirectory();
return true;
// 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);
return 0;
}
// Close platform
static void ClosePlatform(void)
{
glfwDestroyWindow(platform.handle);
glfwTerminate();
}
// 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
static void WindowMaximizeCallback(GLFWwindow *window, int maximized)
{
// TODO.
}
// 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
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
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;
}
// Register fullscreen change events
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_FREE(ptr,c) ((void)(c), RL_FREE(ptr))
#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)
#define NANOSVG_IMPLEMENTATION // Expands implementation
@ -1624,10 +1624,10 @@ void ImageResize(Image *image, int newWidth, int newHeight)
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_GRAY_ALPHA: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 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_R8G8B8A8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 4); 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_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_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_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)4); break;
default: break;
}
@ -1643,7 +1643,7 @@ void ImageResize(Image *image, int newWidth, int newHeight)
Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
// 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;