summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-15 00:26:17 +0200
committerBad Diode <bd@badd10de.dev>2023-04-15 18:29:26 +0200
commita6859fa5c780878a92fbfcd1f12a815fcb1961d6 (patch)
tree09c43083036148d52bde8d120b0798b4fd84530c
parentdd009eb124cf929bee0233b7323b448319e25665 (diff)
downloadgba-renderers-a6859fa5c780878a92fbfcd1f12a815fcb1961d6.tar.gz
gba-renderers-a6859fa5c780878a92fbfcd1f12a815fcb1961d6.zip
Speed up line drawing algorithm
-rw-r--r--src/main.c13
-rw-r--r--src/renderer_m4.c45
2 files changed, 58 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
index 96682f9..d81a26a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -128,6 +128,19 @@ int main(void) {
128 bios_vblank_wait(); 128 bios_vblank_wait();
129 129
130 PROF(test_clear(), test_clear_cycles); 130 PROF(test_clear(), test_clear_cycles);
131 // draw_line(0, 0, 100, 50, 1);
132 // // draw_line(0, 0, 100, 100, 2);
133 // // draw_line(0, 0, 50, 100, 3);
134 // // draw_line(5, 0, 0, 5, 2);
135 // draw_line(100, 0, 0, 50, 1);
136 // // draw_line(100, 0, 0, 100, 2);
137 // // draw_line(50, 0, 0, 100, 3);
138 // txt_render();
139 // txt_clear();
140 // txt_printf("dx: %d\n", dx);
141 // txt_printf("dy: %d\n", dy);
142 // txt_render();
143 // txt_clear();
131 PROF(test_lines(), test_lines_cycles); 144 PROF(test_lines(), test_lines_cycles);
132 PROF(test_rect(), test_rect_cycles); 145 PROF(test_rect(), test_rect_cycles);
133 PROF(test_fill_rect(), test_fill_rect_cycles); 146 PROF(test_fill_rect(), test_fill_rect_cycles);
diff --git a/src/renderer_m4.c b/src/renderer_m4.c
index cbf3c3f..c950763 100644
--- a/src/renderer_m4.c
+++ b/src/renderer_m4.c
@@ -131,6 +131,8 @@ draw_vline(size_t x0, size_t y0, size_t y1, u8 clr) {
131 } 131 }
132} 132}
133 133
134#define SWAP(A,B) do {size_t tmp = (A); (A) = (B); (B) = (tmp);} while(0)
135
134IWRAM_CODE 136IWRAM_CODE
135void 137void
136draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { 138draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
@@ -144,7 +146,49 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
144 MAYBE_SWAP(y0, y1); 146 MAYBE_SWAP(y0, y1);
145 draw_vline(x0, y0, y1, clr); 147 draw_vline(x0, y0, y1, clr);
146 } else { 148 } else {
149#if 1
147 // Diagonal line. 150 // Diagonal line.
151 if (x0 > x1) {
152 SWAP(x0, x1);
153 SWAP(y0, y1);
154 }
155 int dx = x1 - x0;
156 int dy = y0 > y1 ? y0 - y1 : y1 - y0;
157 int x_step = 1;
158 int y_step = y0 > y1 ? -1 : 1;
159 y_step *= SCREEN_WIDTH / 2;
160
161 // Mini-LUT for M4 byte decoding.
162 u16 mask[] = { ~0xFF, 0xFF };
163 u16 color[] = { clr, (clr << 8) };
164 u8 advance[] = { 0, x_step };
165 u16 *dst = &backbuf[(x0 + y0 * SCREEN_WIDTH) / 2];
166 if (dx >= dy) {
167 int diff = 2 * dy - dx;
168 for (int i = dx; i >= 0; i--) {
169 *dst = (*dst & mask[x0 & 1]) | color[x0 & 1];
170 if (diff >= 0) {
171 diff -= 2 * dx;
172 dst = dst + y_step;
173 }
174 diff += 2 * dy;
175 dst = dst + advance[x0 & 1];
176 x0 += x_step;
177 }
178 } else {
179 int diff = 2 * dx - dy;
180 for (int i = dy; i >= 0; i--) {
181 *dst = (*dst & mask[x0 & 1]) | color[x0 & 1];
182 if (diff >= 0) {
183 diff -= 2 * dy;
184 dst = dst + advance[x0 & 1];
185 x0 += x_step;
186 }
187 diff += 2 * dx;
188 dst = dst + y_step;
189 }
190 }
191#else
148 int dx = x0 > x1 ? x0 - x1 : x1 - x0; 192 int dx = x0 > x1 ? x0 - x1 : x1 - x0;
149 int dy = y0 > y1 ? y1 - y0 : y0 - y1; 193 int dy = y0 > y1 ? y1 - y0 : y0 - y1;
150 int x_step = x0 < x1 ? 1 : -1; 194 int x_step = x0 < x1 ? 1 : -1;
@@ -162,6 +206,7 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
162 y0 += y_step; 206 y0 += y_step;
163 } 207 }
164 } 208 }
209#endif
165 } 210 }
166 screen_updated = true; 211 screen_updated = true;
167} 212}