summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/swgfx.h14
-rw-r--r--src/swgfx.c47
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
40typedef struct swgfx swgfx; 40typedef struct swgfx swgfx;
41 41
42swgfx* sgNew(); 42size_t sgMem(int width, int height); // Get memory requirements.
43swgfx* sgNew(int width, int height, void* mem);
43void sgDel(swgfx**); 44void 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
47void sgColourBuffer(swgfx*, sgVec2i dimensions, sgPixel* buffer); 48void sgPresent(swgfx*, sgVec2i dimensions, sgPixel* screen);
48void sgPresent (swgfx*, sgVec2i dimensions, sgPixel* screen);
49 49
50void sgModelId (swgfx*); 50void sgModelId (swgfx*);
51void sgModel (swgfx*, sgVec3 position, sgVec3 right, sgVec3 up, sgVec3 forward); 51void 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
66void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, const sgVec3* positions); 66void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, const sgVec3* positions);
67 67
68void sgCheck(swgfx*); 68void 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)
75void* sgAlloc(size_t count, size_t size);
76void 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
23static constexpr sgVec3 Up3 = (sgVec3){0,1,0}; 22static 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
365static size_t align(size_t size) { 366static 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
372static 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
371void* sgAlloc(size_t count, size_t size) { 378static 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
378void sgFree(void** pp) { 389size_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
386swgfx* sgNew() { 395swgfx* 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
391void sgDel(swgfx** ppSwgfx) { 403void 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
399void sgColourBuffer(swgfx* gfx, sgVec2i dimensions, sgPixel* buffer) {
400 assert(gfx);
401 gfx->dims = dimensions;
402 gfx->colour = buffer;
403}
404
405void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { 410void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) {
406 assert(gfx); 411 assert(gfx);
407 assert(screen); 412 assert(screen);