summaryrefslogtreecommitdiff
path: root/src/renderer_software.c
diff options
context:
space:
mode:
authorRoberto Esteves <contact@robertoesteves.dev>2026-01-05 14:11:50 +0000
committerRoberto Esteves <contact@robertoesteves.dev>2026-01-05 14:11:50 +0000
commit52c6a7635056ee78d282ba2a55eb26f2663bb577 (patch)
tree9d37d851e63e96e53ef3836321f03d4f2839edef /src/renderer_software.c
parentda12440cabe270584ff650703e90db540d2ec4c9 (diff)
refactor some stuff:HEADmaster
- 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.c100
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;
+ }
+ }
+}