diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/command.c | 41 | ||||
| -rw-r--r-- | src/memory.c | 20 | ||||
| -rw-r--r-- | src/renderer_software.c | 100 |
3 files changed, 161 insertions, 0 deletions
diff --git a/src/command.c b/src/command.c new file mode 100644 index 0000000..735036e --- /dev/null +++ b/src/command.c @@ -0,0 +1,41 @@ +#include "rgl.h" + +void RGL_Rect(RGL_Context *ctx, unsigned int x, unsigned int y, + unsigned int width, unsigned int height) { + RGL_Command *rectCommand = + (RGL_Command *)RGL_ArenaAlloc(&ctx->queue.arena, sizeof(RGL_Command)); + + rectCommand->type = Rect; + rectCommand->data.rect.x = x; + rectCommand->data.rect.y = y; + rectCommand->data.rect.width = width; + rectCommand->data.rect.height = height; + rectCommand->data.rect.color = ctx->color; + + ctx->queue.size += 1; +} + +void RGL_BeginPath(RGL_Context *ctx, RGL_PathVerb verb) { + ctx->current = + (RGL_Command *)RGL_ArenaAlloc(&ctx->queue.arena, sizeof(RGL_Command)); + + ctx->current->type = Path; + ctx->current->data.path.color = ctx->color; + ctx->current->data.path.size = 0; + ctx->current->data.path.verb = verb; +} + +void RGL_PathMoveTo(RGL_Context *ctx, int x, int y) { + RGL_Point *p = + (RGL_Point *)RGL_ArenaAlloc(&ctx->queue.arena, sizeof(RGL_Point)); + p->x = RGL_GetFixedI(x); + p->y = RGL_GetFixedI(y); + + ctx->current->data.path.size += 1; +} + +void RGL_EndPath(RGL_Context *ctx) { + ctx->current->data.path.color = ctx->color; + ctx->current = 0; + ctx->queue.size += 1; +} diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..48a7cca --- /dev/null +++ b/src/memory.c @@ -0,0 +1,20 @@ +#include "rgl.h" + +void *RGL_ArenaAlloc(RGL_Arena *arena, unsigned int size) { + void *data = (void *)&(arena->data[arena->size]); + arena->size += size; + + return data; +} + +unsigned int RGL_ArenaCheckpoint(RGL_Arena *arena) { + return arena->size; +} + +void RGL_ArenaRollback(RGL_Arena *arena, unsigned int checkpoint) { + arena->size = checkpoint; +} + +void RGL_ArenaReset(RGL_Arena *arena) { + arena->size = 0; +} 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; + } + } +} |