diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-28 12:57:52 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-28 12:57:52 -0800 |
| commit | 75ee45cc65b35d40355178f48ef0c2d90040b863 (patch) | |
| tree | 780f64e0aa6aefe9ec23f5876113fb7a4120155c | |
| parent | 07fb91b9571fc0add797cbcd0adcc8711401a2be (diff) | |
| -rw-r--r-- | include/swgfx.h | 14 | ||||
| -rw-r--r-- | src/swgfx.c | 47 |
2 files changed, 29 insertions, 32 deletions
diff --git a/include/swgfx.h b/include/swgfx.h index 94eb359..005359b 100644 --- a/include/swgfx.h +++ b/include/swgfx.h | |||
| @@ -39,13 +39,13 @@ typedef struct sgPixel { uint8_t r, g, b, a; } sgPixel; | |||
| 39 | 39 | ||
| 40 | typedef struct swgfx swgfx; | 40 | typedef struct swgfx swgfx; |
| 41 | 41 | ||
| 42 | swgfx* sgNew(); | 42 | size_t sgMem(int width, int height); // Get memory requirements. |
| 43 | swgfx* sgNew(int width, int height, void* mem); | ||
| 43 | void sgDel(swgfx**); | 44 | void sgDel(swgfx**); |
| 44 | 45 | ||
| 45 | // TODO: Write client app first, then implement the functions below in the C file. | 46 | // TODO: Write client app first, then implement the functions below in the C file. |
| 46 | 47 | ||
| 47 | void sgColourBuffer(swgfx*, sgVec2i dimensions, sgPixel* buffer); | 48 | void sgPresent(swgfx*, sgVec2i dimensions, sgPixel* screen); |
| 48 | void sgPresent (swgfx*, sgVec2i dimensions, sgPixel* screen); | ||
| 49 | 49 | ||
| 50 | void sgModelId (swgfx*); | 50 | void sgModelId (swgfx*); |
| 51 | void sgModel (swgfx*, sgVec3 position, sgVec3 right, sgVec3 up, sgVec3 forward); | 51 | void sgModel (swgfx*, sgVec3 position, sgVec3 right, sgVec3 up, sgVec3 forward); |
| @@ -66,11 +66,3 @@ void sgTrianglesIndexed(swgfx*, size_t numIndices, const sgIdx* indices, const s | |||
| 66 | void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, const sgVec3* positions); | 66 | void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, const sgVec3* positions); |
| 67 | 67 | ||
| 68 | void sgCheck(swgfx*); | 68 | void sgCheck(swgfx*); |
| 69 | |||
| 70 | // Memory | ||
| 71 | #define SG_ALIGN 64 | ||
| 72 | #define SG_ALIGN_PTR(P) ((uintptr_t)(P) & (~(SG_ALIGN-1))) | ||
| 73 | #define SG_ALIGN_ALLOC(COUNT, TYPE) (TYPE*)sgAlloc(1, COUNT * sizeof(TYPE)) | ||
| 74 | #define SG_FREE(PP) sgFree((void**)PP) | ||
| 75 | void* sgAlloc(size_t count, size_t size); | ||
| 76 | void sgFree(void**); | ||
diff --git a/src/swgfx.c b/src/swgfx.c index 3b9ce29..54f7432 100644 --- a/src/swgfx.c +++ b/src/swgfx.c | |||
| @@ -17,7 +17,6 @@ Coordinate systems: | |||
| 17 | #include <assert.h> | 17 | #include <assert.h> |
| 18 | #include <math.h> // sqrt | 18 | #include <math.h> // sqrt |
| 19 | #include <stdint.h> | 19 | #include <stdint.h> |
| 20 | #include <stdlib.h> | ||
| 21 | #include <string.h> | 20 | #include <string.h> |
| 22 | 21 | ||
| 23 | static constexpr sgVec3 Up3 = (sgVec3){0,1,0}; | 22 | static constexpr sgVec3 Up3 = (sgVec3){0,1,0}; |
| @@ -361,47 +360,53 @@ static void DrawTriangle3(swgfx* gfx, const sgTri3* tri) { | |||
| 361 | } | 360 | } |
| 362 | 361 | ||
| 363 | #define is_pow2_or_0(X) ((X & (X - 1)) == 0) | 362 | #define is_pow2_or_0(X) ((X & (X - 1)) == 0) |
| 363 | #define SG_ALIGN 64 | ||
| 364 | #define SG_ALLOC(PP_MEM, COUNT, TYPE) (TYPE*)Alloc(PP_MEM, COUNT, sizeof(TYPE)) | ||
| 364 | 365 | ||
| 365 | static size_t align(size_t size) { | 366 | static void* AlignPtr(void* address) { |
| 367 | assert(is_pow2_or_0(SG_ALIGN)); | ||
| 368 | constexpr size_t mask = SG_ALIGN - 1; | ||
| 369 | return (void*)(((uintptr_t)address + mask) & ~mask); | ||
| 370 | } | ||
| 371 | |||
| 372 | static size_t Align(size_t size) { | ||
| 366 | static_assert(is_pow2_or_0(SG_ALIGN)); | 373 | static_assert(is_pow2_or_0(SG_ALIGN)); |
| 367 | constexpr size_t mask = SG_ALIGN - 1; | 374 | constexpr size_t mask = SG_ALIGN - 1; |
| 368 | return (size + mask) & (~mask); | 375 | return (size + mask) & (~mask); |
| 369 | } | 376 | } |
| 370 | 377 | ||
| 371 | void* sgAlloc(size_t count, size_t size) { | 378 | static void* Alloc(void** ppMem, size_t count, size_t size) { |
| 372 | const size_t total = align(count * size); | 379 | assert(ppMem); |
| 373 | void* const ptr = aligned_alloc(SG_ALIGN, total); | 380 | assert(*ppMem); |
| 381 | assert(*ppMem == AlignPtr(*ppMem)); // Should already be aligned. | ||
| 382 | const size_t total = Align(count * size); | ||
| 383 | void* ptr = *ppMem; | ||
| 384 | *ppMem = ptr + total; | ||
| 374 | memset(ptr, 0, total); | 385 | memset(ptr, 0, total); |
| 375 | return ptr; | 386 | return ptr; |
| 376 | } | 387 | } |
| 377 | 388 | ||
| 378 | void sgFree(void** pp) { | 389 | size_t sgMem(int width, int height) { |
| 379 | assert(pp); | 390 | return Align(sizeof(swgfx)) + |
| 380 | if (*pp) { | 391 | Align(width * height * sizeof(sgPixel)) + |
| 381 | free(*pp); | 392 | (SG_ALIGN - 1); // To make room to align allocations within the buffer. |
| 382 | *pp = nullptr; | ||
| 383 | } | ||
| 384 | } | 393 | } |
| 385 | 394 | ||
| 386 | swgfx* sgNew() { | 395 | swgfx* sgNew(int width, int height, void* mem) { |
| 387 | swgfx* gfx = SG_ALIGN_ALLOC(1, swgfx); | 396 | void* aligned = AlignPtr(mem); // Uses the extra room we made in sgMem(). |
| 397 | swgfx* gfx = SG_ALLOC(&aligned, 1, swgfx); | ||
| 398 | gfx->dims = (sgVec2i){width, height}; | ||
| 399 | gfx->colour = SG_ALLOC(&aligned, width * height, sgPixel); | ||
| 388 | return gfx; | 400 | return gfx; |
| 389 | } | 401 | } |
| 390 | 402 | ||
| 391 | void sgDel(swgfx** ppSwgfx) { | 403 | void sgDel(swgfx** ppSwgfx) { |
| 392 | assert(ppSwgfx); | 404 | assert(ppSwgfx); |
| 393 | if (*ppSwgfx) { | 405 | if (*ppSwgfx) { |
| 394 | free(*ppSwgfx); | 406 | *ppSwgfx = nullptr; |
| 395 | *ppSwgfx = 0; | ||
| 396 | } | 407 | } |
| 397 | } | 408 | } |
| 398 | 409 | ||
| 399 | void sgColourBuffer(swgfx* gfx, sgVec2i dimensions, sgPixel* buffer) { | ||
| 400 | assert(gfx); | ||
| 401 | gfx->dims = dimensions; | ||
| 402 | gfx->colour = buffer; | ||
| 403 | } | ||
| 404 | |||
| 405 | void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { | 410 | void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { |
| 406 | assert(gfx); | 411 | assert(gfx); |
| 407 | assert(screen); | 412 | assert(screen); |
