From ea7cd94f7aeb177618db3907a6c86b7252e018f0 Mon Sep 17 00:00:00 2001 From: quou Date: Sat, 1 Jun 2024 12:19:16 +1000 Subject: Initial commit. --- render.c | 380 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 render.c (limited to 'render.c') 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 + ); +} -- cgit v1.2.3-54-g00ecf