improve sw renderer
This commit is contained in:
parent
415d424057
commit
39ee0fefb7
89 changed files with 9380 additions and 2307 deletions
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "pxl8_color.h"
|
||||
#include "pxl8_log.h"
|
||||
#include "pxl8_mem.h"
|
||||
|
||||
typedef struct pxl8_skyline_fit {
|
||||
bool found;
|
||||
|
|
@ -27,6 +28,8 @@ typedef struct pxl8_skyline {
|
|||
struct pxl8_atlas {
|
||||
u32 height, width;
|
||||
u8* pixels;
|
||||
u8* pixels_tiled;
|
||||
u32 tiled_capacity, tiled_size;
|
||||
|
||||
bool dirty;
|
||||
|
||||
|
|
@ -103,7 +106,7 @@ static bool pxl8_skyline_add_rect(pxl8_skyline* skyline, pxl8_point pos, u32 w,
|
|||
|
||||
if (skyline->count - nodes_to_remove + 1 > skyline->capacity) {
|
||||
u32 new_capacity = (skyline->count - nodes_to_remove + 1) * 2;
|
||||
pxl8_skyline_node* new_nodes = (pxl8_skyline_node*)realloc(
|
||||
pxl8_skyline_node* new_nodes = (pxl8_skyline_node*)pxl8_realloc(
|
||||
skyline->nodes,
|
||||
new_capacity * sizeof(pxl8_skyline_node)
|
||||
);
|
||||
|
|
@ -142,44 +145,44 @@ static void pxl8_skyline_compact(pxl8_skyline* skyline) {
|
|||
}
|
||||
|
||||
pxl8_atlas* pxl8_atlas_create(u32 width, u32 height, pxl8_pixel_mode pixel_mode) {
|
||||
pxl8_atlas* atlas = (pxl8_atlas*)calloc(1, sizeof(pxl8_atlas));
|
||||
pxl8_atlas* atlas = (pxl8_atlas*)pxl8_calloc(1, sizeof(pxl8_atlas));
|
||||
if (!atlas) return NULL;
|
||||
|
||||
atlas->height = height;
|
||||
atlas->width = width;
|
||||
|
||||
i32 bytes_per_pixel = pxl8_bytes_per_pixel(pixel_mode);
|
||||
atlas->pixels = (u8*)calloc(width * height, bytes_per_pixel);
|
||||
atlas->pixels = (u8*)pxl8_calloc(width * height, bytes_per_pixel);
|
||||
if (!atlas->pixels) {
|
||||
free(atlas);
|
||||
pxl8_free(atlas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atlas->entry_capacity = PXL8_DEFAULT_ATLAS_ENTRY_CAPACITY;
|
||||
atlas->entries = (pxl8_atlas_entry*)calloc(atlas->entry_capacity, sizeof(pxl8_atlas_entry));
|
||||
atlas->entries = (pxl8_atlas_entry*)pxl8_calloc(atlas->entry_capacity, sizeof(pxl8_atlas_entry));
|
||||
if (!atlas->entries) {
|
||||
free(atlas->pixels);
|
||||
free(atlas);
|
||||
pxl8_free(atlas->pixels);
|
||||
pxl8_free(atlas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atlas->free_capacity = 16;
|
||||
atlas->free_list = (u32*)calloc(atlas->free_capacity, sizeof(u32));
|
||||
atlas->free_list = (u32*)pxl8_calloc(atlas->free_capacity, sizeof(u32));
|
||||
if (!atlas->free_list) {
|
||||
free(atlas->entries);
|
||||
free(atlas->pixels);
|
||||
free(atlas);
|
||||
pxl8_free(atlas->entries);
|
||||
pxl8_free(atlas->pixels);
|
||||
pxl8_free(atlas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atlas->skyline.capacity = 16;
|
||||
atlas->skyline.nodes =
|
||||
(pxl8_skyline_node*)calloc(atlas->skyline.capacity, sizeof(pxl8_skyline_node));
|
||||
(pxl8_skyline_node*)pxl8_calloc(atlas->skyline.capacity, sizeof(pxl8_skyline_node));
|
||||
if (!atlas->skyline.nodes) {
|
||||
free(atlas->free_list);
|
||||
free(atlas->entries);
|
||||
free(atlas->pixels);
|
||||
free(atlas);
|
||||
pxl8_free(atlas->free_list);
|
||||
pxl8_free(atlas->entries);
|
||||
pxl8_free(atlas->pixels);
|
||||
pxl8_free(atlas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -192,11 +195,12 @@ pxl8_atlas* pxl8_atlas_create(u32 width, u32 height, pxl8_pixel_mode pixel_mode)
|
|||
void pxl8_atlas_destroy(pxl8_atlas* atlas) {
|
||||
if (!atlas) return;
|
||||
|
||||
free(atlas->entries);
|
||||
free(atlas->free_list);
|
||||
free(atlas->pixels);
|
||||
free(atlas->skyline.nodes);
|
||||
free(atlas);
|
||||
pxl8_free(atlas->entries);
|
||||
pxl8_free(atlas->free_list);
|
||||
pxl8_free(atlas->pixels);
|
||||
pxl8_free(atlas->pixels_tiled);
|
||||
pxl8_free(atlas->skyline.nodes);
|
||||
pxl8_free(atlas);
|
||||
}
|
||||
|
||||
void pxl8_atlas_clear(pxl8_atlas* atlas, u32 preserve_count) {
|
||||
|
|
@ -209,6 +213,13 @@ void pxl8_atlas_clear(pxl8_atlas* atlas, u32 preserve_count) {
|
|||
atlas->entry_count = preserve_count;
|
||||
atlas->free_count = 0;
|
||||
|
||||
if (preserve_count == 0) {
|
||||
atlas->tiled_size = 0;
|
||||
} else {
|
||||
pxl8_atlas_entry* last = &atlas->entries[preserve_count - 1];
|
||||
atlas->tiled_size = last->tiled_base + (u32)(last->w * last->h);
|
||||
}
|
||||
|
||||
atlas->skyline.nodes[0] = (pxl8_skyline_node){0, 0, (i32)atlas->width};
|
||||
atlas->skyline.count = 1;
|
||||
|
||||
|
|
@ -222,13 +233,13 @@ bool pxl8_atlas_expand(pxl8_atlas* atlas, pxl8_pixel_mode pixel_mode) {
|
|||
u32 new_size = atlas->width * 2;
|
||||
u32 old_width = atlas->width;
|
||||
|
||||
u8* new_pixels = (u8*)calloc(new_size * new_size, bytes_per_pixel);
|
||||
u8* new_pixels = (u8*)pxl8_calloc(new_size * new_size, bytes_per_pixel);
|
||||
if (!new_pixels) return false;
|
||||
|
||||
pxl8_skyline new_skyline;
|
||||
new_skyline.nodes = (pxl8_skyline_node*)calloc(16, sizeof(pxl8_skyline_node));
|
||||
new_skyline.nodes = (pxl8_skyline_node*)pxl8_calloc(16, sizeof(pxl8_skyline_node));
|
||||
if (!new_skyline.nodes) {
|
||||
free(new_pixels);
|
||||
pxl8_free(new_pixels);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -248,8 +259,8 @@ bool pxl8_atlas_expand(pxl8_atlas* atlas, pxl8_pixel_mode pixel_mode) {
|
|||
);
|
||||
|
||||
if (!fit.found) {
|
||||
free(new_skyline.nodes);
|
||||
free(new_pixels);
|
||||
pxl8_free(new_skyline.nodes);
|
||||
pxl8_free(new_pixels);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -269,15 +280,15 @@ bool pxl8_atlas_expand(pxl8_atlas* atlas, pxl8_pixel_mode pixel_mode) {
|
|||
atlas->entries[i].y = fit.pos.y;
|
||||
|
||||
if (!pxl8_skyline_add_rect(&new_skyline, fit.pos, atlas->entries[i].w, atlas->entries[i].h)) {
|
||||
free(new_skyline.nodes);
|
||||
free(new_pixels);
|
||||
pxl8_free(new_skyline.nodes);
|
||||
pxl8_free(new_pixels);
|
||||
return false;
|
||||
}
|
||||
pxl8_skyline_compact(&new_skyline);
|
||||
}
|
||||
|
||||
free(atlas->pixels);
|
||||
free(atlas->skyline.nodes);
|
||||
pxl8_free(atlas->pixels);
|
||||
pxl8_free(atlas->skyline.nodes);
|
||||
|
||||
atlas->pixels = new_pixels;
|
||||
atlas->skyline = new_skyline;
|
||||
|
|
@ -316,7 +327,7 @@ u32 pxl8_atlas_add_texture(
|
|||
} else {
|
||||
if (atlas->entry_count >= atlas->entry_capacity) {
|
||||
u32 new_capacity = atlas->entry_capacity * 2;
|
||||
pxl8_atlas_entry* new_entries = (pxl8_atlas_entry*)realloc(
|
||||
pxl8_atlas_entry* new_entries = (pxl8_atlas_entry*)pxl8_realloc(
|
||||
atlas->entries,
|
||||
new_capacity * sizeof(pxl8_atlas_entry)
|
||||
);
|
||||
|
|
@ -334,6 +345,7 @@ u32 pxl8_atlas_add_texture(
|
|||
entry->y = fit.pos.y;
|
||||
entry->w = w;
|
||||
entry->h = h;
|
||||
entry->log2_w = pxl8_log2(w);
|
||||
|
||||
i32 bytes_per_pixel = pxl8_bytes_per_pixel(pixel_mode);
|
||||
for (u32 y = 0; y < h; y++) {
|
||||
|
|
@ -349,6 +361,30 @@ u32 pxl8_atlas_add_texture(
|
|||
}
|
||||
}
|
||||
|
||||
u32 tiled_tex_size = w * h;
|
||||
u32 new_tiled_size = atlas->tiled_size + tiled_tex_size;
|
||||
if (new_tiled_size > atlas->tiled_capacity) {
|
||||
u32 new_cap = atlas->tiled_capacity ? atlas->tiled_capacity * 2 : 4096;
|
||||
while (new_cap < new_tiled_size) new_cap *= 2;
|
||||
u8* new_tiled = (u8*)pxl8_realloc(atlas->pixels_tiled, new_cap);
|
||||
if (!new_tiled) {
|
||||
entry->active = false;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
atlas->pixels_tiled = new_tiled;
|
||||
atlas->tiled_capacity = new_cap;
|
||||
}
|
||||
|
||||
entry->tiled_base = atlas->tiled_size;
|
||||
u8* tiled_dst = atlas->pixels_tiled + entry->tiled_base;
|
||||
for (u32 ty = 0; ty < h; ty++) {
|
||||
for (u32 tx = 0; tx < w; tx++) {
|
||||
u32 tiled_offset = pxl8_tile_addr(tx, ty, entry->log2_w);
|
||||
tiled_dst[tiled_offset] = pixels[ty * w + tx];
|
||||
}
|
||||
}
|
||||
atlas->tiled_size = new_tiled_size;
|
||||
|
||||
if (!pxl8_skyline_add_rect(&atlas->skyline, fit.pos, w, h)) {
|
||||
entry->active = false;
|
||||
return UINT32_MAX;
|
||||
|
|
@ -377,6 +413,10 @@ const u8* pxl8_atlas_get_pixels(const pxl8_atlas* atlas) {
|
|||
return atlas ? atlas->pixels : NULL;
|
||||
}
|
||||
|
||||
const u8* pxl8_atlas_get_pixels_tiled(const pxl8_atlas* atlas) {
|
||||
return atlas ? atlas->pixels_tiled : NULL;
|
||||
}
|
||||
|
||||
u32 pxl8_atlas_get_width(const pxl8_atlas* atlas) {
|
||||
return atlas ? atlas->width : 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue