11 Commits
Author SHA1 Message Date
Daemo f1c7f8ab27 Added mlx_set_image_rectangle 2026-08-10 16:02:24 +02:00
Daemo 1e27c05789 Merge branch 'indev' of github.com:seekrs/MacroLibX into indev 2026-08-10 15:33:49 +02:00
Daemo 9800d2f78d Added mlx_set_window_icon 2026-08-10 15:32:18 +02:00
Daemo 0491089463 Added deprecation for pixel_put functions (OFF BY DEFAULT) as well as warnings in their descriptions 2026-08-09 02:56:36 +02:00
Daemo 83b9f8f9da Fixed crash on NULL window titles + typo 2026-08-09 02:22:57 +02:00
Daemo f53d90e72c Added a header for event code definition and resize window event 2026-08-09 02:11:37 +02:00
Daemo b9c54dc469 Merge branch 'master' into indev 2026-08-09 00:15:07 +02:00
DaemoandGitHub 63fe3088bf Fix inconsistencies with the FPS scheduler (#241)
The current Fps manager will sometime skip the intended delay and start
the next frame immediately, I'm not 100% sure why it happens, but I
rewrote most of it to stay consistent and improved the overall precision
by compensating for OS wake delay after sleep and finishing with a busy
wait
I also changed the behavior of mlx_set_fps_goal to allow zero/negative
values and treat them as uncapped (like most graphics libraries)
2026-08-08 15:45:56 +02:00
DaemoandGitHub c9df651a14 Optimized region drawing and fixed incorrect region clipping (#240)
Made small optimizations to Texture's SetRegion, SetLinearRegion,
GetRegion and Clear. They might not be super effective depending on how
the compiler already optimized them. The optimizations mainly focus on
removing the multiplication when transforming a position to an index by
using the row index rather than the y coordinate during iteration.
Also fixed regions not drawing properly when clipping against the sides
of a window and made GetRegion reject any region that isn't fully inside
of the window (previously accepted regions that clipped outside of the
right and bottom side, possibly leading to incorrect reads on the user
end due to desynchronized region dimensions)
2026-08-07 12:31:13 +02:00
DaemoandGitHub 2d0c02ae7e Fix freeze when resizing a window (#239)
Fixed an annoying bug where the application would freeze when resizing
the window
This pull request made it so the SDL window's resizing event now
broadcasts a new event specifically asking the swapchain to recreate
itself, which will in turn broadcast the original event when done. It
also removed the Event enum specific values, as they were irrelevant.
2026-08-07 00:18:52 +02:00
ddfbe32cea Indev (#228)
Co-authored-by: kbJeff-8 <kbJeff-8@users.noreply.github.com>
2026-05-13 14:29:51 +02:00
20 changed files with 431 additions and 90 deletions
+2
View File
@@ -177,6 +177,8 @@ int main(void)
mlx.logo_png = mlx_new_image_from_file(mlx.mlx, "42_logo.png", &dummy, &dummy);
mlx.logo_jpg = mlx_new_image_from_file(mlx.mlx, "42_logo.jpg", &dummy, &dummy);
mlx_set_window_icon(mlx.mlx, mlx.win, mlx.logo_png);
mlx_pixel_put(mlx.mlx, mlx.win, 200, 10, (mlx_color){ .rgba = 0xFF00FFFF });
mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo_png, 0, 0);
+17 -5
View File
@@ -148,7 +148,7 @@ MLX_API void mlx_set_window_position(mlx_context mlx, mlx_window win, int x, int
* @brief Sets window size
*
* @param mlx Internal MLX application
* @param win Internal window to move
* @param win Internal window to resize
* @param width New width
* @param height New height
*/
@@ -158,16 +158,25 @@ MLX_API void mlx_set_window_size(mlx_context mlx, mlx_window win, int width, int
* @brief Sets window title
*
* @param mlx Internal MLX application
* @param win Internal window to move
* @param win Internal window to modify
* @param title New title
*/
MLX_API void mlx_set_window_title(mlx_context mlx, mlx_window win, const char* title);
/**
* @brief Sets window icon
*
* @param mlx Internal MLX application
* @param win Internal window to modify
* @param image New icon image
*/
MLX_API void mlx_set_window_icon(mlx_context mlx, mlx_window win, mlx_image image);
/**
* @brief Enables/Disables window fullscreen mode
*
* @param mlx Internal MLX application
* @param win Internal window to move
* @param win Internal window to modify
* @param enable Switch or not to fullscreen
*/
MLX_API void mlx_set_window_fullscreen(mlx_context mlx, mlx_window win, bool enable);
@@ -176,7 +185,7 @@ MLX_API void mlx_set_window_fullscreen(mlx_context mlx, mlx_window win, bool ena
* @brief Gets window position
*
* @param mlx Internal MLX application
* @param win Internal window to move
* @param win Internal window to get from
* @param x Pointers to get position of the window
* @param y Pointers to get position of the window
*/
@@ -186,7 +195,7 @@ MLX_API void mlx_get_window_position(mlx_context mlx, mlx_window win, int* x, in
* @brief Gets window size
*
* @param mlx Internal MLX application
* @param win Internal window to move
* @param win Internal window to get from
* @param x Pointers to get size of the window
* @param y Pointers to get size of the window
*/
@@ -313,7 +322,10 @@ MLX_API void mlx_on_event(mlx_context mlx, mlx_window win, mlx_event_type event,
* @param x X coordinate
* @param y Y coordinate
* @param color Color of the pixel
*
* WARNING: This function isn't performant, consider drawing to an image beforehand.
*/
MLX_DEPRECATED("Use an image rather than directly communicating with the window")
MLX_API void mlx_pixel_put(mlx_context mlx, mlx_window win, int x, int y, mlx_color color);
+19 -1
View File
@@ -75,7 +75,6 @@ MLX_API void mlx_restore_window(mlx_context mlx, mlx_window win);
/* Pixels drawing related functions */
/**
* @brief Put an array of pixels in the window
*
@@ -85,7 +84,12 @@ MLX_API void mlx_restore_window(mlx_context mlx, mlx_window win);
* @param y Y coordinate
* @param pixels Array of pixels
* @param pixels_number Number of pixels
*
* Note: it is responsability of the user to make sure the size of `pixels` is
* big enough for the given array.
* WARNING: This function isn't performant, consider drawing to an image beforehand.
*/
MLX_DEPRECATED("Use an image rather than directly communicating with the window")
MLX_API void mlx_pixel_put_array(mlx_context mlx, mlx_window win, int x, int y, mlx_color* pixels, size_t pixels_number);
/**
@@ -101,13 +105,27 @@ MLX_API void mlx_pixel_put_array(mlx_context mlx, mlx_window win, int x, int y,
*
* Note: it is responsability of the user to make sure the size of `pixels` is
* big enough for the given region.
* WARNING: This function isn't performant, consider drawing to an image beforehand.
*/
MLX_DEPRECATED("Use an image rather than directly communicating with the window")
MLX_API void mlx_pixel_put_region(mlx_context mlx, mlx_window win, int x, int y, int w, int h, mlx_color* pixels);
/* Images related functions */
/**
* @brief Set image rectangle
*
* @param mlx Internal MLX application
* @param img Internal image
* @param x X coordinate in the image
* @param y Y coordinate in the image
* @param w Width of the rectangle
* @param y Height of the rectangle
* @param color Color of the rectangle
*/
MLX_API void mlx_set_image_rectangle(mlx_context mlx, mlx_image image, int x, int y, int w, int h, mlx_color color);
/**
* @brief Get image region
+168
View File
@@ -0,0 +1,168 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mlx_keycodes.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: rprieur <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/08/09 00:15:49 by rprieur #+# #+# */
/* Updated: 2026/08/09 00:16:30 by rprieur ### ########.fr */
/* */
/* ************************************************************************** */
// MacroLibX official repo https://github.com/seekrs/MacroLibX
// MacroLibX official website https://macrolibx.kbz8.me/
#ifndef MACROLIB_X_KEYCODES_H
#define MACROLIB_X_KEYCODES_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Event codes for physical keyboard keys
*/
typedef enum mlx_key_event_code
{
MLX_KEY_A = 4,
MLX_KEY_B = 5,
MLX_KEY_C = 6,
MLX_KEY_D = 7,
MLX_KEY_E = 8,
MLX_KEY_F = 9,
MLX_KEY_G = 10,
MLX_KEY_H = 11,
MLX_KEY_I = 12,
MLX_KEY_J = 13,
MLX_KEY_K = 14,
MLX_KEY_L = 15,
MLX_KEY_M = 16,
MLX_KEY_N = 17,
MLX_KEY_O = 18,
MLX_KEY_P = 19,
MLX_KEY_Q = 20,
MLX_KEY_R = 21,
MLX_KEY_S = 22,
MLX_KEY_T = 23,
MLX_KEY_U = 24,
MLX_KEY_V = 25,
MLX_KEY_W = 26,
MLX_KEY_X = 27,
MLX_KEY_Y = 28,
MLX_KEY_Z = 29,
MLX_KEY_1 = 30,
MLX_KEY_2 = 31,
MLX_KEY_3 = 32,
MLX_KEY_4 = 33,
MLX_KEY_5 = 34,
MLX_KEY_6 = 35,
MLX_KEY_7 = 36,
MLX_KEY_8 = 37,
MLX_KEY_9 = 38,
MLX_KEY_0 = 39,
MLX_KEY_RETURN = 40,
MLX_KEY_ENTER = 40,
MLX_KEY_ESCAPE = 41,
MLX_KEY_BACKSPACE = 42,
MLX_KEY_TAB = 43,
MLX_KEY_SPACE = 44,
MLX_KEY_MINUS = 45,
MLX_KEY_EQUALS = 46,
MLX_KEY_LEFTBRACKET = 47,
MLX_KEY_RIGHTBRACKET = 48,
MLX_KEY_BACKSLASH = 49,
MLX_KEY_SEMICOLON = 51,
MLX_KEY_APOSTROPHE = 52,
MLX_KEY_GRAVE = 53,
MLX_KEY_COMMA = 54,
MLX_KEY_PERIOD = 55,
MLX_KEY_SLASH = 56,
MLX_KEY_CAPSLOCK = 57,
MLX_KEY_F1 = 58,
MLX_KEY_F2 = 59,
MLX_KEY_F3 = 60,
MLX_KEY_F4 = 61,
MLX_KEY_F5 = 62,
MLX_KEY_F6 = 63,
MLX_KEY_F7 = 64,
MLX_KEY_F8 = 65,
MLX_KEY_F9 = 66,
MLX_KEY_F10 = 67,
MLX_KEY_F11 = 68,
MLX_KEY_F12 = 69,
MLX_KEY_PRINTSCREEN = 70,
MLX_KEY_SCROLLLOCK = 71,
MLX_KEY_PAUSE = 72,
MLX_KEY_INSERT = 73,
MLX_KEY_HOME = 74,
MLX_KEY_PAGEUP = 75,
MLX_KEY_DELETE = 76,
MLX_KEY_END = 77,
MLX_KEY_PAGEDOWN = 78,
MLX_KEY_RIGHT = 79,
MLX_KEY_LEFT = 80,
MLX_KEY_DOWN = 81,
MLX_KEY_UP = 82,
MLX_KEY_NUMLOCKCLEAR = 83,
MLX_KEY_KP_DIVIDE = 84,
MLX_KEY_KP_MULTIPLY = 85,
MLX_KEY_KP_MINUS = 86,
MLX_KEY_KP_PLUS = 87,
MLX_KEY_KP_ENTER = 88,
MLX_KEY_KP_1 = 89,
MLX_KEY_KP_2 = 90,
MLX_KEY_KP_3 = 91,
MLX_KEY_KP_4 = 92,
MLX_KEY_KP_5 = 93,
MLX_KEY_KP_6 = 94,
MLX_KEY_KP_7 = 95,
MLX_KEY_KP_8 = 96,
MLX_KEY_KP_9 = 97,
MLX_KEY_KP_0 = 98,
MLX_KEY_KP_PERIOD = 99,
MLX_KEY_LCTRL = 224,
MLX_KEY_LSHIFT = 225,
MLX_KEY_LALT = 226,
MLX_KEY_LGUI = 227,
MLX_KEY_RCTRL = 228,
MLX_KEY_RSHIFT = 229,
MLX_KEY_RALT = 230,
MLX_KEY_RGUI = 231
} mlx_key_codes;
/**
* @brief Event codes for mouse buttons
*/
typedef enum mlx_mouse_code
{
MLX_MOUSE_LEFT = 1,
MLX_MOUSE_MIDDLE = 2,
MLX_MOUSE_RIGHT = 3,
MLX_MOUSE_4 = 4,
MLX_MOUSE_5 = 5,
} mlx_mouse_code;
/**
* @brief Event codes for window events
*/
typedef enum mlx_window_code
{
MLX_WINDOW_CLOSE = 0,
MLX_WINDOW_MOVED = 1,
MLX_WINDOW_MINIMIZED = 2,
MLX_WINDOW_MAXIMIZED = 3,
MLX_WINDOW_ENTER = 4,
MLX_WINDOW_FOCUS = 5,
MLX_WINDOW_LEAVE = 6,
MLX_WINDOW_UNFOCUS = 7,
MLX_WINDOW_SIZE_CHANGED = 8,
MLX_WINDOW_RESIZED = 9,
MLX_WINDOW_RESTORED = 11
} mlx_window_code;
#ifdef __cplusplus
}
#endif
#endif
+19
View File
@@ -83,6 +83,25 @@
#define MLX_API
#endif
#define MLX_NO_DEPRECATE
#ifdef MLX_NO_DEPRECATE
#define MLX_DEPRECATED(msg)
#elif defined(__has_c_attribute)
#if __has_c_attribute(deprecated)
#define MLX_DEPRECATED(msg) [[deprecated(msg)]]
#endif
#endif
#ifndef MLX_DEPRECATED
#if defined(__GNUC__) || defined(__clang__)
#define MLX_DEPRECATED(msg) __attribute__((deprecated(msg)))
#elif defined(_MSC_VER)
#define MLX_DEPRECATED(msg) __declspec(deprecated(msg))
#else
#define MLX_DEPRECATED(msg)
#endif
#endif
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
#define MLX_FUNC_SIG __PRETTY_FUNCTION__
#elif defined(__DMC__) && (__DMC__ >= 0x810)
+1 -1
View File
@@ -23,7 +23,7 @@ namespace mlx
inline void OnEvent(mlx_window win, int event, void(*f)(int, void*), void* param) noexcept;
inline mlx_window NewGraphicsSuport(const mlx_window_create_info* info);
inline mlx_window NewGraphicsSupport(const mlx_window_create_info* info);
inline NonOwningPtr<GraphicsSupport> GetGraphicsSupport(mlx_window win);
inline void DestroyGraphicsSupport(mlx_window win);
+6 -1
View File
@@ -60,7 +60,7 @@ namespace mlx
m_fps.SetMaxFPS(fps);
}
mlx_window Application::NewGraphicsSuport(const mlx_window_create_info* info)
mlx_window Application::NewGraphicsSupport(const mlx_window_create_info* info)
{
MLX_PROFILE_FUNCTION();
if(!info)
@@ -68,6 +68,11 @@ namespace mlx
Error("invalid window create info (NULL)");
return nullptr;
}
if (info->title == nullptr)
{
Error("invalid window title (NULL)");
return nullptr;
}
mlx_window window;
try { window = new mlx_window_handler; }
+4 -3
View File
@@ -19,9 +19,10 @@ namespace mlx
enum class Event
{
ResizeEventCode = 56,
FrameBeginEventCode = 57,
FatalErrorEventCode = 168,
ResizeEventCode = 1,
SwapchainResizeEventCode,
FrameBeginEventCode,
FatalErrorEventCode,
EndEnum
};
+12 -8
View File
@@ -1,26 +1,30 @@
#ifndef __MLX_FPS__
#define __MLX_FPS__
#include <chrono>
namespace mlx
{
typedef std::chrono::steady_clock fps_clock;
class FpsManager
{
public:
FpsManager() = default;
void Init();
bool Update();
inline void SetMaxFPS(std::uint32_t fps) noexcept { m_max_fps = fps; m_ns = 1000000000.0 / fps; }
void WaitUntilNextFrame();
inline void SetMaxFPS(std::uint32_t fps) noexcept { m_target_delta = fps_clock::duration(std::chrono::seconds(1)) / fps;}
~FpsManager() = default;
private:
double m_ns = 1000000000.0 / 1'337'000.0;
std::int64_t m_fps_before = 0;
std::int64_t m_fps_now = 0;
std::int64_t m_timer = 0;
std::uint32_t m_max_fps = 1'337'000;
std::uint32_t m_fps_elapsed_time = 0;
fps_clock::time_point m_current_time;
fps_clock::time_point m_target_time;
fps_clock::time_point m_last_time_record;
fps_clock::duration m_delta_time = fps_clock::duration().zero();
fps_clock::duration m_target_delta = fps_clock::duration().zero();
fps_clock::duration m_sleep_margin = std::chrono::microseconds(200);
};
}
+2
View File
@@ -3,6 +3,7 @@
#include <mlx.h>
#include <Maths/Vec2.h>
#include <Renderer/Image.h>
namespace mlx
{
@@ -26,6 +27,7 @@ namespace mlx
void SetWindowPosition(Handle window, int x, int y) const noexcept;
void SetWindowSize(Handle window, int x, int y) const noexcept;
void SetWindowTitle(Handle window, std::string_view title) const noexcept;
void SetWindowIcon(Handle window, NonOwningPtr<Texture> texture) const noexcept;
void SetWindowFullscreen(Handle window, bool enable) const noexcept;
void SetWindowMaxSize(Handle window, int x, int y) const noexcept;
void SetWindowMinSize(Handle window, int x, int y) const noexcept;
+2
View File
@@ -4,6 +4,7 @@
#include <mlx.h>
#include <Maths/Vec2.h>
#include <Core/SDLManager.h>
#include <Renderer/Image.h>
namespace mlx
{
@@ -24,6 +25,7 @@ namespace mlx
MLX_FORCEINLINE void SetPosition(int x, int y) { SDLManager::Get().SetWindowPosition(p_window, x, y); }
MLX_FORCEINLINE void SetSize(int x, int y) { SDLManager::Get().SetWindowSize(p_window, x, y); m_width = x; m_height = y; }
MLX_FORCEINLINE void SetTitle(std::string title) { SDLManager::Get().SetWindowTitle(p_window, title); m_name = std::move(title); }
MLX_FORCEINLINE void SetIcon(NonOwningPtr<Texture> texture) {SDLManager::Get().SetWindowIcon(p_window, texture); }
MLX_FORCEINLINE void SetFullscreen(bool enable) { SDLManager::Get().SetWindowFullscreen(p_window, enable); }
MLX_FORCEINLINE void SetMaxSize(int x, int y) { SDLManager::Get().SetWindowMaxSize(p_window, x, y); }
MLX_FORCEINLINE void SetMinSize(int x, int y) { SDLManager::Get().SetWindowMinSize(p_window, x, y); }
+3
View File
@@ -86,6 +86,7 @@ namespace mlx
void SetPixel(int x, int y, mlx_color color) noexcept;
void SetRegion(int x, int y, int w, int h, mlx_color* color) noexcept;
void SetLinearRegion(int x, int y, std::size_t len, mlx_color* color) noexcept;
void SetRectangle(int x, int y, int w, int h, mlx_color color) noexcept;
mlx_color GetPixel(int x, int y) noexcept;
void GetRegion(int x, int y, int w, int h, mlx_color* dst) noexcept;
void Clear(VkCommandBuffer cmd, Vec4f color) override;
@@ -94,6 +95,8 @@ namespace mlx
void Swap(Texture& texture) noexcept;
mlx_color* GetBufferCopy() noexcept;
// If a valid cmd buffer is passed, this function takes ownership and makes it invalid after
void SyncCPUBuffer(VkCommandBuffer cmd = VK_NULL_HANDLE);
void Update(VkCommandBuffer cmd);
+2
View File
@@ -1,6 +1,8 @@
#ifndef __MLX_CPU_BUFFER__
#define __MLX_CPU_BUFFER__
#include <PreCompiled.h>
namespace mlx
{
class CPUBuffer
+1 -2
View File
@@ -33,8 +33,7 @@ namespace mlx
while(m_in.IsRunning())
{
if(!m_fps.Update())
continue;
m_fps.WaitUntilNextFrame();
m_in.FetchInputs();
+30 -5
View File
@@ -45,10 +45,9 @@ extern "C"
void mlx_set_fps_goal(mlx_context mlx, int fps)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
if(fps < 0)
mlx::Error("You cannot set a negative FPS cap (nice try)");
else
mlx->app->SetFPSCap(static_cast<std::uint32_t>(fps));
if(fps <= 0)
fps = -1;
mlx->app->SetFPSCap(static_cast<std::uint32_t>(fps));
}
void mlx_destroy_context(mlx_context mlx)
@@ -62,7 +61,7 @@ extern "C"
mlx_window mlx_new_window(mlx_context mlx, const mlx_window_create_info* info)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
return mlx->app->NewGraphicsSuport(info);
return mlx->app->NewGraphicsSupport(info);
}
void mlx_destroy_window(mlx_context mlx, mlx_window win)
@@ -92,12 +91,29 @@ extern "C"
void mlx_set_window_title(mlx_context mlx, mlx_window win, const char* title)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
if (title == nullptr)
{
mlx::Error("invalid window title (NULL)");
return;
}
mlx::NonOwningPtr<mlx::GraphicsSupport> gs = mlx->app->GetGraphicsSupport(win);
if(!gs && !gs->HasWindow())
return;
gs->GetWindow()->SetTitle(title);
}
void mlx_set_window_icon(mlx_context mlx, mlx_window win, mlx_image image)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
mlx::NonOwningPtr<mlx::GraphicsSupport> gs = mlx->app->GetGraphicsSupport(win);
if(!gs && !gs->HasWindow())
return;
mlx::NonOwningPtr<mlx::Texture> texture = mlx->app->GetTexture(image);
if(!texture)
return;
gs->GetWindow()->SetIcon(texture);
}
void mlx_set_window_fullscreen(mlx_context mlx, mlx_window win, bool enable)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
@@ -441,6 +457,15 @@ extern "C"
gs->PixelPutRegion(x, y, w, h, pixels);
}
void mlx_set_image_rectangle(mlx_context mlx, mlx_image image, int x, int y, int w, int h, mlx_color color)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
mlx::NonOwningPtr<mlx::Texture> texture = mlx->app->GetTexture(image);
if(!texture)
return;
texture->SetRectangle(x, y, w, h, color);
}
void mlx_get_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, mlx_color* dst)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
+23 -16
View File
@@ -1,30 +1,37 @@
#include <PreCompiled.h>
#include <Core/Fps.h>
#ifndef __APPLE__
#include <emmintrin.h>
#endif
namespace mlx
{
void FpsManager::Init()
{
m_timer = static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
m_fps_before = m_timer;
m_fps_now = m_timer;
m_current_time = fps_clock::now();
m_target_time = m_current_time + m_target_delta;
}
bool FpsManager::Update()
void FpsManager::WaitUntilNextFrame()
{
using namespace std::chrono_literals;
m_fps_now = static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
if(std::chrono::duration<std::uint64_t>{m_fps_now - m_timer} >= 1s)
m_timer += m_fps_now;
m_fps_elapsed_time = m_fps_now - m_fps_before;
if(m_fps_elapsed_time >= m_ns)
m_current_time = fps_clock::now();
if(m_current_time < m_target_time)
{
m_fps_before += m_ns;
return true;
std::this_thread::sleep_until(m_target_time - m_sleep_margin);
m_current_time = fps_clock::now();
while (m_current_time < m_target_time)
{
#ifndef __APPLE__
_mm_pause(); // reduces CPU usage on x86 without yielding
#endif
m_current_time = fps_clock::now();
}
}
std::this_thread::sleep_for(std::chrono::duration<double, std::nano>(m_ns - 1));
return false;
else if (m_target_time < m_current_time - m_target_delta * 4)
m_target_time = m_current_time;
m_target_time += m_target_delta;
m_delta_time = m_current_time - m_last_time_record;
m_last_time_record = m_current_time;
}
}
+27 -1
View File
@@ -1,3 +1,5 @@
#include "Utils/Buffer.h"
#include "mlx.h"
#include <PreCompiled.h>
#include <Core/SDLManager.h>
#include <Core/Memory.h>
@@ -56,7 +58,12 @@ namespace mlx
infos->window = SDL_CreateWindow(info->title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, info->width, info->height, flags);
if(!infos->window)
FatalError("SDL: unable to open a new window; %", SDL_GetError());
infos->icon = SDL_CreateRGBSurfaceFrom(static_cast<void*>(logo_mlx), logo_mlx_width, logo_mlx_height, 32, 4 * logo_mlx_width, Rmask(), Gmask(), Bmask(), Amask());
mlx_color* buffer = new mlx_color[logo_mlx_size];
std::memcpy(buffer, logo_mlx, logo_mlx_size);
infos->icon = SDL_CreateRGBSurfaceFrom(buffer, logo_mlx_width, logo_mlx_height, 32, logo_mlx_width * 4, Rmask(), Gmask(), Bmask(), Amask());
if(!infos->icon)
FatalError("SDL: unable to create a window icon; %", SDL_GetError());
SDL_SetWindowIcon(infos->window, infos->icon);
m_windows_registry.insert(infos);
@@ -74,7 +81,10 @@ namespace mlx
if(infos->window != nullptr)
SDL_DestroyWindow(infos->window);
if(infos->icon != nullptr)
{
delete[] (mlx_color*)infos->icon->pixels;
SDL_FreeSurface(infos->icon);
}
m_windows_registry.erase(infos);
delete infos;
@@ -152,6 +162,21 @@ namespace mlx
SDL_SetWindowTitle(static_cast<Internal::WindowInfos*>(window)->window, title.data());
}
void SDLManager::SetWindowIcon(Handle window, NonOwningPtr<Texture> texture) const noexcept
{
Internal::WindowInfos* infos = static_cast<Internal::WindowInfos*>(window);
if(infos->icon != nullptr)
{
delete[] (mlx_color*)infos->icon->pixels;
SDL_FreeSurface(infos->icon);
}
int width = texture->GetWidth(), height = texture->GetHeight();
infos->icon = SDL_CreateRGBSurfaceFrom(texture->GetBufferCopy(), width, height, 32, width * 4, Rmask(), Gmask(), Bmask(), Amask());
SDL_SetWindowIcon(infos->window, infos->icon);
}
void SDLManager::SetWindowFullscreen(Handle window, bool enable) const noexcept
{
SDL_SetWindowFullscreen(static_cast<Internal::WindowInfos*>(window)->window, (enable ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0));
@@ -276,6 +301,7 @@ namespace mlx
case SDL_WINDOWEVENT_LEAVE: functor(MLX_WINDOW_EVENT, id, 6); break;
case SDL_WINDOWEVENT_FOCUS_LOST: functor(MLX_WINDOW_EVENT, id, 7); break;
case SDL_WINDOWEVENT_SIZE_CHANGED: functor(MLX_WINDOW_EVENT, id, 8); break;
case SDL_WINDOWEVENT_RESIZED: functor(MLX_WINDOW_EVENT, id, 9); break;
case SDL_WINDOWEVENT_RESTORED: functor(MLX_WINDOW_EVENT, id, 11); break;
default : break;
+3 -3
View File
@@ -8,9 +8,9 @@ namespace mlx
{
namespace Internal
{
struct ResizeEventBroadcast : public EventBase
struct SwapchainResizeEventBroadcast : public EventBase
{
Event What() const override { return Event::ResizeEventCode; }
Event What() const override { return Event::SwapchainResizeEventCode; }
};
}
@@ -23,7 +23,7 @@ namespace mlx
if(!m_events_hooks.contains(window_id) || m_events_hooks[window_id][event].empty())
return;
if(event == MLX_WINDOW_EVENT && code == 8)
EventBus::SendBroadcast(Internal::ResizeEventBroadcast{});
EventBus::SendBroadcast(Internal::SwapchainResizeEventBroadcast{});
for(const auto& hook : m_events_hooks[window_id][event])
{
if(hook.fn)
+82 -36
View File
@@ -1,3 +1,5 @@
#include "Utils/Buffer.h"
#include "mlx.h"
#include <PreCompiled.h>
#include <Renderer/Image.h>
#include <Maths/Vec4.h>
@@ -226,25 +228,34 @@ namespace mlx
void Texture::SetRegion(int x, int y, int w, int h, mlx_color* pixels) noexcept
{
MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) >= m_width || static_cast<std::uint32_t>(y) >= m_height)
return;
if(w < 0 || h < 0)
if(w < 0 || h < 0 || x < -w || y < -h
|| x >= static_cast<int>(m_width) || y >= static_cast<int>(m_height))
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
for(std::uint32_t i = 0, moving_x = x, moving_y = y;; i++, moving_x++)
const int
start_x = std::max<int>(x, 0),
start_y = std::max<int>(y, 0),
start_row = start_y * m_width,
start_i = (start_y - y) * w + (start_x - x),
end_x = std::min<int>(x + w, m_width),
end_y = std::min<int>(y + h, m_height),
end_row = end_y * m_width,
incr = (x + w) - end_x + (start_x - x);
for(int i = start_i, dx = start_x, row = start_row;; i++, dx++)
{
if(moving_x >= static_cast<std::uint32_t>(x + w) || moving_x >= m_width)
if(dx >= end_x)
{
moving_x = x;
moving_y++;
if(moving_y >= static_cast<std::uint32_t>(y + h) || moving_y >= m_height)
i += incr;
dx = start_x;
row += m_width;
if(row >= end_row)
break;
}
if constexpr(std::endian::native == std::endian::little)
m_staging_buffer->GetMap<mlx_color*>()[(moving_y * m_width) + moving_x] = ReverseColor(pixels[i]);
m_staging_buffer->GetMap<mlx_color*>()[row + dx] = ReverseColor(pixels[i]);
else
m_staging_buffer->GetMap<mlx_color*>()[(moving_y * m_width) + moving_x] = pixels[i];
m_staging_buffer->GetMap<mlx_color*>()[row + dx] = pixels[i];
}
m_has_been_modified = true;
}
@@ -252,23 +263,55 @@ namespace mlx
void Texture::SetLinearRegion(int x, int y, std::size_t len, mlx_color* pixels) noexcept
{
MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) >= m_width || static_cast<std::uint32_t>(y) >= m_height)
if(x >= static_cast<int>(m_width) || y >= static_cast<int>(m_height))
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
int
start = y * m_width + x,
dest_start = std::max<int>(start, 0),
src_start = dest_start - start,
dest_end = std::min<int>(start + len, m_width * m_height);
if constexpr(std::endian::native == std::endian::little)
{
for(std::size_t i = 0; i < len && (y * m_width) + x + i < m_width * m_height; i++)
m_staging_buffer->GetMap<mlx_color*>()[(y * m_width) + x + i] = ReverseColor(pixels[i]);
for(int i = dest_start, j = src_start; i < dest_end; i++, j++)
m_staging_buffer->GetMap<mlx_color*>()[i] = ReverseColor(pixels[j]);
}
else
{
std::size_t len_guard;
if((y * m_width + x + len) < m_width * m_height)
len_guard = len;
std::memcpy(
&m_staging_buffer->GetMap<mlx_color*>()[dest_start],
&pixels[src_start], dest_end - dest_start);
}
m_has_been_modified = true;
}
void Texture::SetRectangle(int x, int y, int w, int h, mlx_color color) noexcept
{
MLX_PROFILE_FUNCTION();
if(w < 0 || h < 0 || x < -w || y < -h
|| x >= static_cast<int>(m_width) || y >= static_cast<int>(m_height))
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
const int
start_x = std::max<int>(x, 0),
start_row = std::max<int>(y, 0) * m_width,
end_x = std::min<int>(x + w, m_width),
end_row = std::min<int>(y + h, m_height) * m_width;
for(int dx = start_x, row = start_row;; dx++)
{
if(dx >= end_x)
{
dx = start_x;
row += m_width;
if(row >= end_row)
break;
}
if constexpr(std::endian::native == std::endian::little)
m_staging_buffer->GetMap<mlx_color*>()[row + dx] = ReverseColor(color);
else
len_guard = len - (m_width * m_height - (y * m_width + x + len));
std::memcpy(&m_staging_buffer->GetMap<mlx_color*>()[(y * m_width) + x], pixels, len_guard);
m_staging_buffer->GetMap<mlx_color*>()[row + dx] = color;
}
m_has_been_modified = true;
}
@@ -289,23 +332,23 @@ namespace mlx
void Texture::GetRegion(int x, int y, int w, int h, mlx_color* dst) noexcept
{
MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) >= m_width || static_cast<std::uint32_t>(y) >= m_height)
if(w < 0 || h < 0 || x < 0 || y < 0 || static_cast<std::uint32_t>(x + w) >= m_width || static_cast<std::uint32_t>(y + h) >= m_height)
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
for(std::uint32_t i = 0, moving_x = x, moving_y = y;; i++, moving_x++)
for(std::uint32_t i = 0, dx = x, row = y * m_width;; i++, dx++)
{
if(moving_x >= static_cast<std::uint32_t>(x + w) || moving_x >= m_width)
if(dx >= m_width)
{
moving_x = x;
moving_y++;
if(moving_y >= static_cast<std::uint32_t>(y + h) || moving_y >= m_height)
dx = x;
row += m_width;
if(row >= m_height * m_width)
break;
}
if constexpr(std::endian::native == std::endian::little)
dst[i] = ReverseColor(m_staging_buffer->GetMap<mlx_color*>()[(moving_y * m_width) + moving_x]);
dst[i] = ReverseColor(m_staging_buffer->GetMap<mlx_color*>()[row + dx]);
else
dst[i] = m_staging_buffer->GetMap<mlx_color*>()[(moving_y * m_width) + moving_x];
dst[i] = m_staging_buffer->GetMap<mlx_color*>()[row + dx];
}
}
@@ -320,16 +363,8 @@ namespace mlx
processed_color.g = static_cast<std::uint8_t>(color.g * 255.f);
processed_color.b = static_cast<std::uint8_t>(color.b * 255.f);
processed_color.a = static_cast<std::uint8_t>(color.a * 255.f);
if(processed_color.r == 0 && processed_color.g == 0 && processed_color.b == 0)
std::memset(m_staging_buffer->GetMap(), processed_color.a, m_staging_buffer->GetSize());
else
{
for(std::size_t y = 0; y < m_height; y++)
{
for(std::size_t x = 0; x < m_width; x++)
m_staging_buffer->GetMap<mlx_color*>()[y * m_width + x] = processed_color;
}
}
for(std::size_t i = 0; i < m_width * m_height; i++)
m_staging_buffer->GetMap<mlx_color*>()[i] = processed_color;
}
}
@@ -346,6 +381,17 @@ namespace mlx
m_has_been_modified = false;
}
mlx_color* Texture::GetBufferCopy() noexcept
{
MLX_PROFILE_FUNCTION();
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
mlx_color* dst = new mlx_color[m_width * m_height];
std::memcpy(dst, m_staging_buffer->GetMap<mlx_color*>(), m_width * m_height * sizeof(mlx_color));
return dst;
}
void Texture::OpenCPUBuffer()
{
MLX_PROFILE_FUNCTION();
+1 -1
View File
@@ -161,7 +161,7 @@ namespace mlx
std::function<void(const EventBase&)> functor = [this](const EventBase& event)
{
if(event.What() == Event::ResizeEventCode && !m_resize)
if(event.What() == Event::SwapchainResizeEventCode && !m_resize)
m_resize = true;
};
EventBus::RegisterListener({ functor, "mlx_swapchain_" + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });