summaryrefslogtreecommitdiff
path: root/render.c
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-06-01 12:19:16 +1000
committerquou <quou@disroot.org>2024-06-01 12:20:17 +1000
commitea7cd94f7aeb177618db3907a6c86b7252e018f0 (patch)
treee972f9cf590ef756c2e41f3eac5b03e16db08300 /render.c
Initial commit.
Diffstat (limited to 'render.c')
-rw-r--r--render.c380
1 files changed, 380 insertions, 0 deletions
diff --git a/render.c b/render.c
new file mode 100644
index 0000000..e291e7d
--- /dev/null
+++ b/render.c
@@ -0,0 +1,380 @@
+#include "plat.h"
+#include "maths.h"
+#include "render.h"
+
+static struct {
+ Rectangle clip;
+} renderer;
+
+Colour make_colour(unsigned rgb, unsigned char a) {
+ Colour r;
+ r.r = (unsigned char)(rgb >> 16);
+ r.g = (unsigned char)(rgb >> 8);
+ r.b = (unsigned char)rgb;
+ r.a = a;
+ return r;
+}
+
+Colour make_black() {
+ Colour r = { 0, 0, 0, 255 };
+ return r;
+}
+
+Colour make_white() {
+ return make_colour(0xffffff, 255);
+}
+
+void init_bitmap(
+ Bitmap* bitmap,
+ Colour* pixels,
+ int w,
+ int h
+) {
+ bitmap->pixels = pixels;
+ bitmap->w = w;
+ bitmap->h = h;
+}
+
+void render_init(void) {
+ int i, e;
+ Colour b, * p;
+ b = make_black();
+ p = get_fb();
+ e = get_render_w() * get_render_h();
+ for (i = 0; i < e; i++)
+ p[i] = b;
+}
+
+void render_begin(void) {
+ int i, e;
+ Colour b, * p;
+ b = make_black();
+ p = get_fb();
+ e = get_render_w() * get_render_h();
+ for (i = 0; i < e; i++)
+ p[i] = b;
+ render_reset_clip();
+}
+
+void render_clear(void) {
+ render_clear_col(make_black());
+}
+
+void render_clear_col(Colour col) {
+ Colour* d;
+ int ox, x, y, ex, ey, w;
+ d = get_fb();
+ x = renderer.clip.x;
+ y = renderer.clip.y;
+ ex = renderer.clip.w;
+ ey = renderer.clip.h;
+ ox = x;
+ w = get_render_w();
+ for (; y < ey; y++)
+ for (x = ox; x < ex; x++)
+ d[x + y * w] = col;
+}
+
+void render_clip(const Rectangle* rect) {
+ renderer.clip = *rect;
+ renderer.clip.x = maxi(renderer.clip.x, 0);
+ renderer.clip.y = maxi(renderer.clip.y, 0);
+ renderer.clip.w = mini(
+ renderer.clip.w,
+ get_render_w()
+ );
+ renderer.clip.h = mini(
+ renderer.clip.h,
+ get_render_h()
+ );
+}
+
+void render_reset_clip(void) {
+ renderer.clip.x = 0;
+ renderer.clip.y = 0;
+ renderer.clip.w = get_render_w();
+ renderer.clip.h = get_render_h();
+}
+
+Colour* get_render_pixels(void) {
+ return get_fb();
+}
+
+Colour blend(Colour dst, Colour src) {
+ int ima;
+
+ ima = 0xff - src.a;
+ dst.r = (unsigned char)(((src.r * src.a) + (dst.r * ima)) >> 8);
+ dst.g = (unsigned char)(((src.g * src.a) + (dst.g * ima)) >> 8);
+ dst.b = (unsigned char)(((src.b * src.a) + (dst.b * ima)) >> 8);
+
+ return dst;
+}
+
+Colour blend_mod(Colour dst, Colour src, Colour mod) {
+ int ima;
+
+ src.a = (src.a * mod.a) >> 8;
+ ima = 0xff - src.a;
+ dst.r = (unsigned char)(((src.r * mod.r * src.a) >> 16) + ((dst.r * ima) >> 8));
+ dst.g = (unsigned char)(((src.g * mod.g * src.a) >> 16) + ((dst.g * ima) >> 8));
+ dst.b = (unsigned char)(((src.b * mod.b * src.a) >> 16) + ((dst.b * ima) >> 8));
+
+ return dst;
+}
+
+#define blit_vars(t_) \
+ int i, j, stride, sstride, n; \
+ Colour* dst; \
+ const t_* src; \
+ Rectangle sub;
+#define blit( \
+ src_, \
+ dst_, \
+ pitch_, \
+ clip_, \
+ src_w_, \
+ src_h_, \
+ expr_ \
+) \
+ sub = *rect; \
+ if (sub.w <= 0) { goto end; } \
+ if (sub.h <= 0) { goto end; } \
+ if (sub.w > (src_w_)) { goto end; } \
+ if (sub.h > (src_h_)) { goto end; } \
+ if ((n = (clip_).x - x) > 0) { \
+ sub.w -= n; \
+ sub.x += n; \
+ x += n; \
+ } \
+ if ((n = (clip_).y - y) > 0) { \
+ sub.h -= n; \
+ sub.y += n; \
+ y += n; \
+ } \
+ if ((n = x + sub.w - (clip_).w) > 0) { \
+ sub.w -= n; \
+ } \
+ if ((n = y + sub.h - (clip_).h) > 0) { \
+ sub.h -= n; \
+ } \
+ if (sub.w <= 0) { goto end; } \
+ if (sub.h <= 0) { goto end; } \
+ dst = (dst_) + (x + y * (pitch_)); \
+ src = (src_) + (sub.x + sub.y * (src_w_)); \
+ stride = (pitch_) - sub.w; \
+ sstride = (src_w_) - sub.w; \
+ for (i = 0; i < sub.h; i++) { \
+ for (j = 0; j < sub.w; j++) { \
+ expr_; \
+ dst++; \
+ src++; \
+ } \
+ dst += stride; \
+ src += sstride; \
+ } \
+ end:
+
+#define blit_rect_vars \
+ int x1, y1, x2, y2, dr, j, i; \
+ Colour* dst;
+#define blit_rect(dst_, pitch_, clip_) \
+ x1 = rect->x < (clip_).x ? (clip_).x : rect->x; \
+ y1 = rect->y < (clip_).y ? (clip_).y : rect->y; \
+ x2 = rect->x + rect->w; \
+ y2 = rect->y + rect->h; \
+ x2 = x2 > (clip_).w? (clip_).w: x2; \
+ y2 = y2 > (clip_).h? (clip_).h: y2; \
+ dst = dst_; \
+ dst += x1 + y1 * pitch_; \
+ dr = pitch_ - (x2 - x1); \
+ for (j = y1; j < y2; j++) { \
+ for (i = x1; i < x2; i++) { \
+ *dst = blend(*dst, colour); \
+ dst++; \
+ } \
+ dst += dr; \
+ }
+
+void render_bitmap(
+ const Bitmap* bitmap,
+ int x,
+ int y,
+ const Rectangle* rect
+) {
+ blit_vars(Colour)
+ int renderer_w;
+ Colour* renderer_pixels;
+ renderer_w = get_render_w();
+ renderer_pixels = get_fb();
+ blit(
+ bitmap->pixels,
+ renderer_pixels,
+ renderer_w,
+ renderer.clip,
+ bitmap->w,
+ bitmap->h,
+ *dst = blend(*dst, *src)
+ );
+}
+
+void render_bitmap_col(
+ const Bitmap* bitmap,
+ int x,
+ int y,
+ const Rectangle* rect,
+ Colour colour
+) {
+ blit_vars(Colour)
+ int renderer_w;
+ Colour* renderer_pixels;
+ renderer_w = get_render_w();
+ renderer_pixels = get_fb();
+ blit(
+ bitmap->pixels,
+ renderer_pixels,
+ renderer_w,
+ renderer.clip,
+ bitmap->w,
+ bitmap->h,
+ *dst = blend_mod(*dst, *src, colour)
+ );
+}
+
+void render_mask(
+ const unsigned char* pixels,
+ int x,
+ int y,
+ int w,
+ int h,
+ const Rectangle* rect,
+ Colour colour
+) {
+ blit_vars(unsigned char)
+ int renderer_w;
+ Colour c;
+ Colour* renderer_pixels;
+ renderer_w = get_render_w();
+ renderer_pixels = get_fb();
+ c = colour;
+ blit(
+ pixels,
+ renderer_pixels,
+ renderer_w,
+ renderer.clip,
+ w,
+ h,
+ {
+ c.a = colour.a * *src;
+ *dst = blend(*dst, c);
+ }
+ );
+}
+
+void render_rect(
+ const Rectangle* rect,
+ Colour colour
+) {
+ blit_rect_vars
+ int renderer_w;
+ Colour* renderer_pixels;
+ renderer_w = get_render_w();
+ renderer_pixels = get_fb();
+ blit_rect(
+ renderer_pixels,
+ renderer_w,
+ renderer.clip
+ );
+}
+
+void rcopy(
+ Bitmap* to,
+ const Bitmap* from,
+ int x,
+ int y,
+ const Rectangle* rect
+) {
+ Rectangle clip;
+ blit_vars(Colour);
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = to->w;
+ clip.h = to->h;
+ blit(
+ from->pixels,
+ to->pixels,
+ to->w,
+ clip,
+ from->w,
+ from->h,
+ *dst = blend(*dst, *src)
+ );
+}
+
+void rcopy_col(
+ Bitmap* to,
+ const Bitmap* from,
+ int x,
+ int y,
+ const Rectangle* rect,
+ Colour colour
+) {
+ Rectangle clip;
+ blit_vars(Colour)
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = to->w;
+ clip.h = to->h;
+ blit(
+ from->pixels,
+ to->pixels,
+ to->w,
+ clip,
+ from->w,
+ from->h,
+ *dst = blend_mod(*dst, *src, colour);
+ );
+}
+
+void rcopy_ac(
+ Bitmap* to,
+ const Bitmap* from,
+ int x,
+ int y,
+ const Rectangle* rect,
+ unsigned char t
+) {
+ Rectangle clip;
+ blit_vars(Colour)
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = to->w;
+ clip.h = to->h;
+ blit(
+ from->pixels,
+ to->pixels,
+ to->w,
+ clip,
+ from->w,
+ from->h,
+ *dst = src->a > t ? *src : *dst;
+ );
+}
+
+void rcopy_rect(
+ Bitmap* to,
+ const Rectangle* rect,
+ Colour colour
+) {
+ Rectangle clip;
+ blit_rect_vars
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = to->w;
+ clip.h = to->h;
+ blit_rect(
+ to->pixels,
+ to->w,
+ clip
+ );
+}