From 0ebb1f200e222d143bc5015a1c218cff723f1999 Mon Sep 17 00:00:00 2001
From: koniifer <aurlex1@gmail.com>
Date: Tue, 15 Oct 2024 21:11:06 +0100
Subject: [PATCH] make surface example more interesting, optimise memory
 filling

---
 sysdata/libraries/render/src/software.hb      | 90 +++++--------------
 .../render_example/src/examples/surface.hb    | 38 ++++----
 .../src/examples/tactical_screen.hb           |  2 +-
 sysdata/programs/render_example/src/main.hb   |  2 +-
 4 files changed, 47 insertions(+), 85 deletions(-)

diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb
index 3dcbd09..ae8905b 100644
--- a/sysdata/libraries/render/src/software.hb
+++ b/sysdata/libraries/render/src/software.hb
@@ -4,23 +4,6 @@
 
 framebuffer := @as(^Color, idk)
 
-// init := fn(): void {
-// 	width := dt.get(int, "framebuffer/fb0/width\0")
-// 	height := dt.get(int, "framebuffer/fb0/height\0")
-// 	pixels := width * height
-// 	back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
-// 	ctx = Context.{
-// 		fb: dt.get(^Color, "framebuffer/fb0/ptr\0"),
-// 		bb: back_buffer,
-// 		buf: back_buffer,
-// 		width,
-// 		height,
-// 		pixels,
-// 		double_buffer: true,
-// 	}
-// 	return
-// }
-
 init := fn(double_buffer: bool): Surface {
 	framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
 	width := dt.get(int, "framebuffer/fb0/width\0")
@@ -49,37 +32,22 @@ put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void {
 	return
 }
 
-// put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
-// 	start_idx := @inline(screenidx, surface, pos.x, pos.y)
-// 	end_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y)
-
-// 	loop if start_idx >= end_idx break else {
-// 		@inline(memory.set, Color, &color, surface.buf + start_idx, @bitcast(tr.x))
-// 		start_idx += surface.width
-// 	}
-
-// 	return
-// }
-
 put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
-	top_start_idx := @inline(screenidx, surface, pos.x, pos.y)
-	bottom_start_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y - 1)
-	rows_to_fill := tr.y / 2
-	top_cursor := 0
-	bottom_cursor := (tr.y - 1) * surface.width
-	i := 0
-	loop if i == rows_to_fill break else {
-		@inline(memory.set, Color, &color, surface.buf + top_start_idx, @bitcast(tr.x))
-		@inline(memory.set, Color, &color, surface.buf + bottom_start_idx, @bitcast(tr.x))
+	top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y)
+	bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y - 1)
+	rows_to_fill := tr.y
+
+	loop if rows_to_fill <= 1 break else {
+		@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
+		@inline(memory.set, Color, &color, bottom_start_idx, @bitcast(tr.x))
 
 		top_start_idx += surface.width
 		bottom_start_idx -= surface.width
-		i += 1
+		rows_to_fill -= 2
 	}
 
-	if tr.y % 2 != 0 {
-		middle_idx := @inline(screenidx, surface, pos.x, pos.y + rows_to_fill)
-		@inline(memory.set, Color, &color, surface.buf + middle_idx, @bitcast(tr.x))
+	if rows_to_fill == 1 {
+		@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
 	}
 
 	return
@@ -168,40 +136,26 @@ put_line := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): vo
 	return
 }
 
-// put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void {
-// 	start_idx := @inline(screenidx, surface, pos.x, pos.y)
-// 	end_idx := @inline(screenidx, surface, pos.x, pos.y + top.height)
-// 	cursor := top.width * top.height
-
-// 	loop if start_idx >= end_idx break else {
-// 		@inline(memory.copy, Color, top.buf + cursor, surface.buf + start_idx, @intcast(top.width))
-// 		start_idx += surface.width
-// 		cursor -= top.width
-// 	}
-// 	return
-// }
-
 put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void {
-	top_start_idx := @inline(screenidx, surface, pos.x, pos.y)
-	bottom_start_idx := @inline(screenidx, surface, pos.x, pos.y + top.height - 1)
-	rows_to_copy := top.height / 2
-	top_cursor := 0
-	bottom_cursor := top.width * (top.height - 1)
-	i := 0
-	loop if i == rows_to_copy break else {
-		@inline(memory.copy, Color, top.buf + top_cursor, surface.buf + top_start_idx, @intcast(top.width))
-		@inline(memory.copy, Color, top.buf + bottom_cursor, surface.buf + bottom_start_idx, @intcast(top.width))
+	top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y)
+	bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + top.height - 1)
+	rows_to_copy := top.height
+	top_cursor := top.buf
+	bottom_cursor := top.buf + top.width * (top.height - 1)
+
+	loop if rows_to_copy <= 1 break else {
+		@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
+		@inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width))
 
 		top_start_idx += surface.width
 		bottom_start_idx -= surface.width
 		top_cursor += top.width
 		bottom_cursor -= top.width
-		i += 1
+		rows_to_copy -= 2
 	}
 
-	if top.height % 2 != 0 {
-		middle_idx := @inline(screenidx, surface, pos.x, pos.y + rows_to_copy)
-		@inline(memory.copy, Color, top.buf + top_cursor, surface.buf + middle_idx, @intcast(top.width))
+	if rows_to_copy == 1 {
+		@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
 	}
 
 	return
diff --git a/sysdata/programs/render_example/src/examples/surface.hb b/sysdata/programs/render_example/src/examples/surface.hb
index 95fbd51..7eec6d4 100644
--- a/sysdata/programs/render_example/src/examples/surface.hb
+++ b/sysdata/programs/render_example/src/examples/surface.hb
@@ -1,30 +1,37 @@
-.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math
+.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math;
+.{random} := @use("../../../../libraries/stn/src/lib.hb")
 render := @use("../../../../libraries/render/src/lib.hb")
 
 /* expected result:
-       the lines example bounces around the screen */
+   the square example bounces around the screen */
 
 example := fn(): void {
 	screen := render.init(true)
 
 	image := render.new_surface(341, 256)
-
-	p0 := Vec2(int).(0, 0)
-	p1 := Vec2(int).(0, image.height)
-	render.clear(image, .(100, 50, 0, 255))
-	loop if p0.y >= image.height break else {
-		render.put_line(image, p0, p1, .(255, 180, 100, 255))
-		render.put_line(image, .(image.width, image.height) - p0, .(image.width, image.height) - p1, .(255, 180, 100, 255))
-		p0.y += image.height >> 6
-		p1.x += image.width >> 6
-	}
-
-	vel := Vec2(int).(1, 1)
+	vel := Vec2(int).(-1, -1)
 	pos := Vec2(int).(100, 100)
+	vel_inner := Vec2(int).(1, 1)
+	pos_inner := Vec2(int).(10, 10)
+	color := @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
 	loop {
+		render.clear(image, render.black)
+		render.clear(screen, render.black)
+
+		render.put_filled_rect(image, pos_inner, .(100, 100), color)
+		render.put_rect(image, .(0, 0), .(image.width - 1, image.height - 1), render.white)
+
 		render.put_surface(screen, image, pos)
 		render.sync(screen)
-		render.clear(screen, render.black)
+
+		if pos_inner.x == 0 | pos_inner.x == image.width - 100 {
+			vel_inner.x = -vel_inner.x
+			color = @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
+		}
+		if pos_inner.y == 0 | pos_inner.y == image.height - 100 {
+			vel_inner.y = -vel_inner.y
+			color = @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
+		}
 
 		if pos.x == 0 | pos.x == screen.width - image.width {
 			vel.x = -vel.x
@@ -34,6 +41,7 @@ example := fn(): void {
 		}
 
 		pos += vel
+		pos_inner += vel_inner
 	}
 	return
 }
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/tactical_screen.hb b/sysdata/programs/render_example/src/examples/tactical_screen.hb
index 5b2e909..bbbaed2 100644
--- a/sysdata/programs/render_example/src/examples/tactical_screen.hb
+++ b/sysdata/programs/render_example/src/examples/tactical_screen.hb
@@ -4,7 +4,7 @@ Vec2 := math.Vec2
 
 /* expected result:
    a grid of green lines scrolling from the left top corner to the right bottom one
-   with a "target" randomly apperaing in one of them and a "seeker" "catching" it*/
+   with a "target" randomly apperaing in one of them and a "seeker" "catching" it */
 
 example := fn(): void {
 	screen := render.init(true)
diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb
index 1ce2d4e..a3981b6 100644
--- a/sysdata/programs/render_example/src/main.hb
+++ b/sysdata/programs/render_example/src/main.hb
@@ -1,4 +1,4 @@
-.{example} := @use("./examples/image.hb")
+.{example} := @use("./examples/surface.hb")
 
 main := fn(): void {
 	@inline(example)