aboutsummaryrefslogtreecommitdiff
path: root/teensy/teensy_renderer.c
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-05-10 00:28:14 -0400
committeriamcheeseman <[email protected]>2026-05-10 00:28:14 -0400
commit576bd27e11ec70bdbd1b9a644d2e227b57586337 (patch)
tree2dc41e3f88bb95568f73ee372fc35512afcbcf9b /teensy/teensy_renderer.c
parent9ed5698b3c74c7ce1784d3bebe2aa73d5a0c319d (diff)
i ain't splitting alla this up
Diffstat (limited to 'teensy/teensy_renderer.c')
-rw-r--r--teensy/teensy_renderer.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/teensy/teensy_renderer.c b/teensy/teensy_renderer.c
new file mode 100644
index 0000000..b29e485
--- /dev/null
+++ b/teensy/teensy_renderer.c
@@ -0,0 +1,217 @@
+#include "teensy_renderer.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "teensy_context.h"
+#include "teensy_list.h"
+
+struct ty_renderer r;
+
+static
+bool is_renderer_init(void)
+{
+ return r.screen.data != NULL && r.screen.width * r.screen.height != 0;
+}
+
+static
+void image_bounds_check(struct ty_image img, struct ty_vec2i pos)
+{
+#ifdef TEENSY_DEBUG
+ if (
+ pos.x < 0 ||
+ pos.x >= img.width ||
+ pos.y < 0 ||
+ pos.y >= img.height
+ ) {
+ ty_log_fatal(
+ TY_ERR_RENDER_OOB,
+ "OOB (%d, %d). bounds are (%d, %d)",
+ pos.x, pos.y,
+ img.width, img.height
+ );
+ }
+#else
+ (void)img;
+ (void)pos;
+#endif
+}
+
+void ty_init_renderer(void)
+{
+ r.screen = ty_create_image(
+ ctx.hints.scr_width,
+ ctx.hints.scr_height,
+ NULL
+ );
+}
+
+void ty_deinit_renderer(void)
+{
+ assert(is_renderer_init());
+
+ ty_free_image(r.screen);
+}
+
+struct ty_image ty_create_image(int w, int h, const struct ty_color* data)
+{
+ struct ty_image img;
+
+ img.width = w;
+ img.height = h;
+
+ size_t size = sizeof(struct ty_color) * w * h;
+ img.data = ty_alloc(size);
+ if (data)
+ memcpy(img.data, data, size);
+ else
+ memset(img.data, 0, size);
+
+ return img;
+}
+
+void ty_free_image(struct ty_image img)
+{
+ ty_free(img.data);
+}
+
+struct ty_color ty_img_get_pixel(struct ty_image img, struct ty_vec2i pos)
+{
+ image_bounds_check(img, pos);
+ return img.data[pos.y * img.width + pos.x];
+}
+
+void ty_img_set_pixel(
+ struct ty_image img,
+ struct ty_vec2i pos,
+ struct ty_color color
+) {
+ image_bounds_check(img, pos);
+ img.data[pos.y * img.width + pos.x] = color;
+}
+
+void ty_draw_clear(struct ty_color col)
+{
+ assert(is_renderer_init());
+ for (int i = 0; i < r.screen.width * r.screen.height; i++) {
+ r.screen.data[i] = col;
+ }
+}
+
+void ty_draw_image(struct ty_image img, struct ty_vec2i pos)
+{
+ int x1 = fmin(fmax(floor(pos.x), 0), r.screen.width);
+ int y1 = fmin(fmax(floor(pos.y), 0), r.screen.height);
+ int x2 = fmin(fmax(floor(pos.x + img.width), 0), r.screen.width);
+ int y2 = fmin(fmax(floor(pos.y + img.height), 0), r.screen.height);
+
+ for (int dy = y1; dy < y2; dy++) {
+ for (int dx = x1; dx < x2; dx++) {
+ ty_img_set_pixel(
+ r.screen,
+ ty_vec2i(dx, dy),
+ ty_img_get_pixel(img, ty_vec2i(dx - x1, dy - y1))
+ );
+ }
+ }
+}
+
+void ty_draw_image_ex(
+ struct ty_image img,
+ struct ty_recti src,
+ struct ty_recti dst
+) {
+ int x1 = fmin(fmax(floor(dst.x), 0), r.screen.width);
+ int y1 = fmin(fmax(floor(dst.y), 0), r.screen.height);
+ int x2 = fmin(fmax(floor(dst.x + dst.w), 0), r.screen.width);
+ int y2 = fmin(fmax(floor(dst.y + dst.h), 0), r.screen.height);
+
+ for (int dy = y1; dy < y2; dy++) {
+ for (int dx = x1; dx < x2; dx++) {
+ int img_x = ((dx - x1) * src.w) / dst.w + src.x;
+ int img_y = ((dy - y1) * src.h) / dst.h + src.y;
+
+ ty_img_set_pixel(
+ r.screen,
+ ty_vec2i(dx, dy),
+ ty_img_get_pixel(img, ty_vec2i(img_x, img_y))
+ );
+ }
+ }
+}
+
+void ty_draw_rect(struct ty_recti rect, struct ty_color color)
+{
+ int x1 = fmin(fmax(floor(rect.x), 0), r.screen.width);
+ int y1 = fmin(fmax(floor(rect.y), 0), r.screen.height);
+
+ int x2 = fmin(fmax(floor(rect.x + rect.w), 0), r.screen.width);
+ int y2 = fmin(fmax(floor(rect.y + rect.h), 0), r.screen.height);
+
+ for (int dy = y1; dy < y2; dy++) {
+ for (int dx = x1; dx < x2; dx++) {
+ ty_img_set_pixel(
+ r.screen,
+ ty_vec2i(dx, dy),
+ color
+ );
+ }
+ }
+}
+
+void ty_draw_line(
+ struct ty_vec2i start,
+ struct ty_vec2i end,
+ struct ty_color color
+) {
+ int dx = end.x - start.x;
+ int dy = end.y - start.y;
+
+ if (abs(dx) > abs(dy)) {
+ if (start.x > end.x) {
+ int tmp = start.x;
+ start.x = end.x;
+ end.x = tmp;
+
+ tmp = start.y;
+ start.y = end.y;
+ end.y = tmp;
+ }
+
+ for (int x = start.x; x < end.x; x++) {
+ int y = start.y + dy * (x - start.x) / dx;
+
+ ty_img_set_pixel(
+ r.screen,
+ ty_vec2i(x, y),
+ color
+ );
+ }
+ } else {
+ if (start.y > end.y) {
+ int tmp = start.x;
+ start.x = end.x;
+ end.x = tmp;
+
+ tmp = start.y;
+ start.y = end.y;
+ end.y = tmp;
+ }
+
+ for (int y = start.y; y < end.y; y++) {
+ int x = start.x + dx * (y - start.y) / dy;
+
+ ty_img_set_pixel(
+ r.screen,
+ ty_vec2i(x, y),
+ color
+ );
+ }
+ }
+}
+
+void ty_draw_end(void)
+{
+ assert(is_renderer_init());
+}