true 16-bit color... glorious

This commit is contained in:
asrael 2025-11-28 14:41:35 -06:00
parent 3dccce8a81
commit b1e8525c3e
30 changed files with 678 additions and 652 deletions

View file

@ -5,6 +5,7 @@
#include <stdlib.h>
#include <string.h>
#include "pxl8_color.h"
#include "pxl8_macros.h"
typedef struct pxl8_skyline_fit {
@ -82,7 +83,7 @@ static pxl8_skyline_fit pxl8_skyline_find_position(
return result;
}
static void pxl8_skyline_add_rect(pxl8_skyline* skyline, pxl8_point pos, u32 w, u32 h) {
static bool pxl8_skyline_add_rect(pxl8_skyline* skyline, pxl8_point pos, u32 w, u32 h) {
u32 node_idx = 0;
for (u32 i = 0; i < skyline->count; i++) {
if (skyline->nodes[i].x == pos.x) {
@ -101,11 +102,14 @@ static void pxl8_skyline_add_rect(pxl8_skyline* skyline, pxl8_point pos, u32 w,
}
if (skyline->count - nodes_to_remove + 1 > skyline->capacity) {
skyline->capacity = (skyline->count - nodes_to_remove + 1) * 2;
skyline->nodes = (pxl8_skyline_node*)realloc(
u32 new_capacity = (skyline->count - nodes_to_remove + 1) * 2;
pxl8_skyline_node* new_nodes = (pxl8_skyline_node*)realloc(
skyline->nodes,
skyline->capacity * sizeof(pxl8_skyline_node)
new_capacity * sizeof(pxl8_skyline_node)
);
if (!new_nodes) return false;
skyline->nodes = new_nodes;
skyline->capacity = new_capacity;
}
if (nodes_to_remove > 0) {
@ -118,6 +122,7 @@ static void pxl8_skyline_add_rect(pxl8_skyline* skyline, pxl8_point pos, u32 w,
skyline->nodes[node_idx] = (pxl8_skyline_node){pos.x, pos.y + (i32)h, (i32)w};
skyline->count = skyline->count - nodes_to_remove + 1;
return true;
}
static void pxl8_skyline_compact(pxl8_skyline* skyline) {
@ -143,14 +148,14 @@ pxl8_atlas* pxl8_atlas_create(u32 width, u32 height, pxl8_color_mode color_mode)
atlas->height = height;
atlas->width = width;
i32 bytes_per_pixel = (color_mode == PXL8_COLOR_MODE_HICOLOR) ? 4 : 1;
i32 bytes_per_pixel = pxl8_bytes_per_pixel(color_mode);
atlas->pixels = (u8*)calloc(width * height, bytes_per_pixel);
if (!atlas->pixels) {
free(atlas);
return NULL;
}
atlas->entry_capacity = 64;
atlas->entry_capacity = PXL8_DEFAULT_ATLAS_ENTRY_CAPACITY;
atlas->entries = (pxl8_atlas_entry*)calloc(atlas->entry_capacity, sizeof(pxl8_atlas_entry));
if (!atlas->entries) {
free(atlas->pixels);
@ -197,7 +202,7 @@ void pxl8_atlas_destroy(pxl8_atlas* atlas) {
bool pxl8_atlas_expand(pxl8_atlas* atlas, pxl8_color_mode color_mode) {
if (!atlas || atlas->width >= 4096) return false;
i32 bytes_per_pixel = (color_mode == PXL8_COLOR_MODE_HICOLOR) ? 4 : 1;
i32 bytes_per_pixel = pxl8_bytes_per_pixel(color_mode);
u32 new_size = atlas->width * 2;
u32 old_width = atlas->width;
@ -236,8 +241,8 @@ bool pxl8_atlas_expand(pxl8_atlas* atlas, pxl8_color_mode color_mode) {
for (u32 x = 0; x < (u32)atlas->entries[i].w; x++) {
u32 src_idx = (atlas->entries[i].y + y) * old_width + (atlas->entries[i].x + x);
u32 dst_idx = (fit.pos.y + y) * new_size + (fit.pos.x + x);
if (bytes_per_pixel == 4) {
((u32*)new_pixels)[dst_idx] = ((u32*)atlas->pixels)[src_idx];
if (bytes_per_pixel == 2) {
((u16*)new_pixels)[dst_idx] = ((u16*)atlas->pixels)[src_idx];
} else {
new_pixels[dst_idx] = atlas->pixels[src_idx];
}
@ -247,7 +252,11 @@ bool pxl8_atlas_expand(pxl8_atlas* atlas, pxl8_color_mode color_mode) {
atlas->entries[i].x = fit.pos.x;
atlas->entries[i].y = fit.pos.y;
pxl8_skyline_add_rect(&new_skyline, fit.pos, atlas->entries[i].w, atlas->entries[i].h);
if (!pxl8_skyline_add_rect(&new_skyline, fit.pos, atlas->entries[i].w, atlas->entries[i].h)) {
free(new_skyline.nodes);
free(new_pixels);
return false;
}
pxl8_skyline_compact(&new_skyline);
}
@ -290,11 +299,14 @@ u32 pxl8_atlas_add_texture(
texture_id = atlas->free_list[--atlas->free_count];
} else {
if (atlas->entry_count >= atlas->entry_capacity) {
atlas->entry_capacity *= 2;
atlas->entries = (pxl8_atlas_entry*)realloc(
u32 new_capacity = atlas->entry_capacity * 2;
pxl8_atlas_entry* new_entries = (pxl8_atlas_entry*)realloc(
atlas->entries,
atlas->entry_capacity * sizeof(pxl8_atlas_entry)
new_capacity * sizeof(pxl8_atlas_entry)
);
if (!new_entries) return UINT32_MAX;
atlas->entries = new_entries;
atlas->entry_capacity = new_capacity;
}
texture_id = atlas->entry_count++;
}
@ -307,21 +319,24 @@ u32 pxl8_atlas_add_texture(
entry->w = w;
entry->h = h;
i32 bytes_per_pixel = (color_mode == PXL8_COLOR_MODE_HICOLOR) ? 4 : 1;
i32 bytes_per_pixel = pxl8_bytes_per_pixel(color_mode);
for (u32 y = 0; y < h; y++) {
for (u32 x = 0; x < w; x++) {
u32 src_idx = y * w + x;
u32 dst_idx = (fit.pos.y + y) * atlas->width + (fit.pos.x + x);
if (bytes_per_pixel == 4) {
((u32*)atlas->pixels)[dst_idx] = ((const u32*)pixels)[src_idx];
if (bytes_per_pixel == 2) {
((u16*)atlas->pixels)[dst_idx] = ((const u16*)pixels)[src_idx];
} else {
atlas->pixels[dst_idx] = pixels[src_idx];
}
}
}
pxl8_skyline_add_rect(&atlas->skyline, fit.pos, w, h);
if (!pxl8_skyline_add_rect(&atlas->skyline, fit.pos, w, h)) {
entry->active = false;
return UINT32_MAX;
}
pxl8_skyline_compact(&atlas->skyline);
atlas->dirty = true;