implementing last functions, adding put pixel region

This commit is contained in:
2024-12-16 16:13:44 +01:00
parent feb3fcbd1f
commit 623021a669
10 changed files with 201 additions and 18 deletions

View File

@@ -25,6 +25,8 @@ namespace mlx
inline void ResetRenderData(int color) noexcept;
inline void PixelPut(int x, int y, int color) noexcept;
inline void PixelPutArray(int x, int y, int* pixels, std::size_t pixels_size) noexcept;
inline void PixelPutRegion(int x, int y, int w, int h, int* pixels) noexcept;
inline void StringPut(int x, int y, int, std::string str);
inline void TexturePut(NonOwningPtr<class Texture> texture, int x, int y, float scale_x, float scale_y, float angle);

View File

@@ -30,6 +30,30 @@ namespace mlx
}
}
void GraphicsSupport::PixelPutArray(int x, int y, int* pixels, std::size_t pixels_size) noexcept
{
MLX_PROFILE_FUNCTION();
NonOwningPtr<Texture> texture = m_put_pixel_manager.DrawPixelsArray(x, y, m_draw_layer, pixels, pixels_size);
if(texture)
{
m_pixelput_called = true;
Sprite& new_sprite = p_scene->CreateSprite(texture);
new_sprite.SetPosition(Vec2f{ 0.0f, 0.0f });
}
}
void GraphicsSupport::PixelPutRegion(int x, int y, int w, int h, int* pixels) noexcept
{
MLX_PROFILE_FUNCTION();
NonOwningPtr<Texture> texture = m_put_pixel_manager.DrawPixelsRegion(x, y, w, h, m_draw_layer, pixels);
if(texture)
{
m_pixelput_called = true;
Sprite& new_sprite = p_scene->CreateSprite(texture);
new_sprite.SetPosition(Vec2f{ 0.0f, 0.0f });
}
}
void GraphicsSupport::StringPut(int x, int y, int color, std::string str)
{
MLX_PROFILE_FUNCTION();

View File

@@ -12,10 +12,15 @@ namespace mlx
// Returns a valid pointer when a new texture has been created
NonOwningPtr<Texture> DrawPixel(int x, int y, std::uint64_t draw_layer, int color);
NonOwningPtr<Texture> DrawPixelsArray(int x, int y, std::uint64_t draw_layer, int* pixels, std::size_t pixels_size);
NonOwningPtr<Texture> DrawPixelsRegion(int x, int y, int w, int h, std::uint64_t draw_layer, int* pixels);
void ResetRenderData();
~PutPixelManager() = default;
private:
NonOwningPtr<Texture> GetLayer(std::uint64_t draw_layer, bool& is_newlayer);
private:
std::unordered_map<std::uint64_t, NonOwningPtr<Texture>> m_placements;
std::vector<std::unique_ptr<Texture>> m_textures;

View File

@@ -84,7 +84,10 @@ namespace mlx
void Destroy() noexcept override;
void SetPixel(int x, int y, int color) noexcept;
void SetRegion(int x, int y, int w, int h, int* pixels) noexcept;
void SetLinearRegion(int x, int y, std::size_t len, int* pixels) noexcept;
int GetPixel(int x, int y) noexcept;
void GetRegion(int x, int y, int w, int h, int* dst) noexcept;
void Update(VkCommandBuffer cmd);

16
runtime/Includes/Utils/Bits.h git.filemode.normal_file
View File

@@ -0,0 +1,16 @@
#ifndef __MLX_BITS__
#define __MLX_BITS__
namespace mlx
{
template<std::integral T>
constexpr T ByteSwap(T value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>, "T may not have padding bits");
auto value_representation = std::bit_cast<std::array<std::byte, sizeof(T)>>(value);
std::ranges::reverse(value_representation);
return std::bit_cast<T>(value_representation);
}
}
#endif

View File

@@ -381,12 +381,22 @@ extern "C"
gs->GetWindow()->Restore();
}
void mlx_pixel_put_array(mlx_context mlx, mlx_window win, int x, int y, int* pixels)
void mlx_pixel_put_array(mlx_context mlx, mlx_window win, int x, int y, int* pixels, size_t pixels_size)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
mlx::NonOwningPtr<mlx::GraphicsSupport> gs = mlx->app->GetGraphicsSupport(win);
if(!gs)
return;
gs->PixelPutArray(x, y, pixels, pixels_size);
}
void mlx_pixel_put_region(mlx_context mlx, mlx_window win, int x, int y, int w, int h, int* pixels)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
mlx::NonOwningPtr<mlx::GraphicsSupport> gs = mlx->app->GetGraphicsSupport(win);
if(!gs)
return;
gs->PixelPutRegion(x, y, w, h, pixels);
}
void mlx_get_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, int* dst)
@@ -395,6 +405,7 @@ extern "C"
mlx::NonOwningPtr<mlx::Texture> texture = mlx->app->GetTexture(image);
if(!texture)
return;
texture->GetRegion(x, y, w, h, dst);
}
void mlx_set_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, int* pixels)
@@ -403,6 +414,7 @@ extern "C"
mlx::NonOwningPtr<mlx::Texture> texture = mlx->app->GetTexture(image);
if(!texture)
return;
texture->SetRegion(x, y, w, h, pixels);
}
void mlx_put_transformed_image_to_window(mlx_context mlx, mlx_window win, mlx_image image, int x, int y, float scale_x, float scale_y, float angle)

View File

@@ -7,6 +7,40 @@ namespace mlx
{
NonOwningPtr<Texture> PutPixelManager::DrawPixel(int x, int y, std::uint64_t draw_layer, int color)
{
MLX_PROFILE_FUNCTION();
bool is_newlayer;
NonOwningPtr<Texture> layer = GetLayer(draw_layer, is_newlayer);
if(!layer)
return nullptr;
layer->SetPixel(x, y, color);
return (is_newlayer ? layer : nullptr);
}
NonOwningPtr<Texture> PutPixelManager::DrawPixelsArray(int x, int y, std::uint64_t draw_layer, int* pixels, std::size_t pixels_size)
{
MLX_PROFILE_FUNCTION();
bool is_newlayer;
NonOwningPtr<Texture> layer = GetLayer(draw_layer, is_newlayer);
if(!layer)
return nullptr;
layer->SetLinearRegion(x, y, pixels_size, pixels);
return (is_newlayer ? layer : nullptr);
}
NonOwningPtr<Texture> PutPixelManager::DrawPixelsRegion(int x, int y, int w, int h, std::uint64_t draw_layer, int* pixels)
{
MLX_PROFILE_FUNCTION();
bool is_newlayer;
NonOwningPtr<Texture> layer = GetLayer(draw_layer, is_newlayer);
if(!layer)
return nullptr;
layer->SetRegion(x, y, w, h, pixels);
return (is_newlayer ? layer : nullptr);
}
NonOwningPtr<Texture> PutPixelManager::GetLayer(std::uint64_t draw_layer, bool& is_newlayer)
{
MLX_PROFILE_FUNCTION();
Verify((bool)p_renderer, "invalid renderer pointer");
VkExtent2D extent;
@@ -20,9 +54,10 @@ namespace mlx
auto it = m_placements.find(draw_layer);
if(it != m_placements.end())
{
it->second->SetPixel(x, y, color);
return nullptr;
is_newlayer = false;
return it->second;
}
is_newlayer = true;
bool adjusment = false;
if(m_current_texture_index >= m_textures.size())
@@ -39,12 +74,11 @@ namespace mlx
{
m_placements[draw_layer] = m_textures.at(m_current_texture_index - adjusment).get();
m_textures.at(m_current_texture_index - adjusment)->Clear(VK_NULL_HANDLE, Vec4f{ 0.0f });
m_textures.at(m_current_texture_index - adjusment)->SetPixel(x, y, color);
return m_textures.at(m_current_texture_index - adjusment).get();
}
catch(...)
{
Error("PutPixelManager: invalid texture index; % is not in range of 0-% (internal mlx issue, please report to devs)", m_current_texture_index - 1, m_textures.size());
Error("PutPixelManager: invalid texture index; % is not in range of 0-% (internal mlx issue, please report to devs)", m_current_texture_index - adjusment, m_textures.size());
return nullptr;
}
}

View File

@@ -5,6 +5,7 @@
#include <Renderer/RenderCore.h>
#include <Utils/CallOnExit.h>
#include <Core/Memory.h>
#include <Utils/Bits.h>
#define STB_IMAGE_IMPLEMENTATION
@@ -215,12 +216,49 @@ namespace mlx
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
// Needs to reverse bytes order because why not
unsigned char bytes[4];
bytes[0] = (color >> 24) & 0xFF;
bytes[1] = (color >> 16) & 0xFF;
bytes[2] = (color >> 8) & 0xFF;
bytes[3] = color & 0xFF;
m_cpu_buffer[(y * m_width) + x] = *reinterpret_cast<int*>(bytes);
color = ByteSwap(color);
m_cpu_buffer[(y * m_width) + x] = color;
m_has_been_modified = true;
}
void Texture::SetRegion(int x, int y, int w, int h, int* 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)
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
for(std::uint32_t i = 0, moving_x = x, moving_y = y;; i++, moving_x++)
{
if(moving_x >= static_cast<std::uint32_t>(x + w) || moving_x >= m_width)
{
moving_x = x;
if(moving_y >= static_cast<std::uint32_t>(y + h) || moving_y >= m_height)
break;
moving_y++;
}
// Needs to reverse bytes order because why not
int color = ByteSwap(pixels[i]);
m_cpu_buffer[(moving_y * m_width) + moving_x] = color;
}
m_has_been_modified = true;
}
void Texture::SetLinearRegion(int x, int y, std::size_t len, int* 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(!m_staging_buffer.has_value())
OpenCPUBuffer();
for(std::size_t i = 0; i < len; i++)
{
// Needs to reverse bytes order because why not
int color = ByteSwap(pixels[i]);
m_cpu_buffer[(y * m_width) + x + i] = color;
}
m_has_been_modified = true;
}
@@ -234,6 +272,27 @@ namespace mlx
return m_cpu_buffer[(y * m_width) + x];
}
void Texture::GetRegion(int x, int y, int w, int h, int* 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)
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
for(std::uint32_t i = 0, moving_x = x, moving_y = y;; i++, moving_x++)
{
if(moving_x >= static_cast<std::uint32_t>(x + w) || moving_x >= m_width)
{
moving_x = x;
if(moving_y >= static_cast<std::uint32_t>(y + h) || moving_y >= m_height)
break;
moving_y++;
}
// Needs to reverse bytes order because why not
dst[i] = ByteSwap(m_cpu_buffer[(moving_y * m_width) + moving_x]);
}
}
void Texture::Update(VkCommandBuffer cmd)
{
MLX_PROFILE_FUNCTION();