diff options
| author | Roberto Esteves <contact@robertoesteves.dev> | 2026-01-05 14:11:50 +0000 |
|---|---|---|
| committer | Roberto Esteves <contact@robertoesteves.dev> | 2026-01-05 14:11:50 +0000 |
| commit | 52c6a7635056ee78d282ba2a55eb26f2663bb577 (patch) | |
| tree | 9d37d851e63e96e53ef3836321f03d4f2839edef /src/renderer_software.c | |
| parent | da12440cabe270584ff650703e90db540d2ec4c9 (diff) | |
- add meson build system
- refactor executable to be a test
- remove stdlib from base library
Diffstat (limited to 'src/renderer_software.c')
| -rw-r--r-- | src/renderer_software.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/renderer_software.c b/src/renderer_software.c new file mode 100644 index 0000000..3cdd614 --- /dev/null +++ b/src/renderer_software.c @@ -0,0 +1,100 @@ +#include "rgl.h" + +void RGL_DrawRect(RGL_Buffer *buf, RGL_Command *cmd) { + unsigned int x, y, insideX, insideY; + + RGL_ASSERT(cmd->type != Rect, "expected rectangle type"); + for (y = 0; y < buf->height; ++y) { + for (x = 0; x < buf->width; ++x) { + insideX = x >= cmd->data.rect.x && + x <= (cmd->data.rect.x + cmd->data.rect.width); + insideY = y >= cmd->data.rect.y && + y <= (cmd->data.rect.y + cmd->data.rect.height); + + if (insideX && insideY) { + buf->data[x + (y * buf->width)] = cmd->data.rect.color; + } + } + } +} + +void RGL_DrawStroke(RGL_Buffer *buf, RGL_PathHeader *path, RGL_Point *points) { + RGL_Point p1, p2; + unsigned int i; + int x0, x1, y0, y1, dx, dy, sx, sy, idx, err, e2; + + for (i = 0; i < path->size; ++i) { + p1 = points[i], p2 = points[(i + 1) % path->size]; + + x0 = RGL_FixedToInt(p1.x), y0 = RGL_FixedToInt(p1.y); + x1 = RGL_FixedToInt(p2.x), y1 = RGL_FixedToInt(p2.y); + + dx = RGL_ABS(x1 - x0); + sx = x0 < x1 ? 1 : -1; + + dy = -RGL_ABS(y1 - y0); + sy = y0 < y1 ? 1 : -1; + + err = dx + dy; + while (1) { + idx = x0 + (y0 * buf->width); + if (idx < buf->width * buf->height) { + buf->data[idx] = path->color; + } + + if (x0 == x1 && y0 == y1) + break; + + e2 = err * 2; + if (e2 >= dy) { + err += dy; + x0 += sx; + } + + if (e2 <= dx) { + err += dx; + y0 += sy; + } + } + } +} + +void RGL_DrawPath(RGL_Buffer *buf, RGL_PathHeader *path, RGL_Point *points) { + switch (path->verb) { + case PathStroke: { + RGL_DrawStroke(buf, path, points); + } break; + case PathFill: { + /* RGL_DrawFill(buf, path, points, col); */ + RGL_CRASH("`RGL_DrawFill` not implemented"); + } break; + default: { + RGL_CRASH("tried to handle unknown `path->verb`"); + } break; + } +} + +void RGL_Draw(RGL_Context *ctx, RGL_Buffer *buf) { + RGL_Command cmd; + int i; + for (i = 0; i < ctx->queue.size; ++i) { + cmd = ctx->queue.commands[i]; + switch (cmd.type) { + case Rect: { + RGL_DrawRect(buf, &cmd); + } break; + case Path: { + RGL_Point *points = (RGL_Point *)&(ctx->queue.commands[i + 1]); + RGL_DrawPath(buf, &cmd.data.path, points); + + /* Skip point list, so it points to a valid command */ + ctx->queue.commands = + (RGL_Command *)((char *)ctx->queue.commands + + cmd.data.path.size * sizeof(RGL_Point)); + } break; + default: { + RGL_CRASH("unknown `cmd.type`"); + } break; + } + } +} |