summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-17 12:02:35 +0200
committerBad Diode <bd@badd10de.dev>2023-04-17 12:02:35 +0200
commit579f18c54565728c6efb50edee40ca27f86d2fcc (patch)
tree63afac7181eceecab15df2c0c6130fc123f906da
parent70d6b8a2cbe4c7343297f466132ac2d7ce1a652d (diff)
downloadgba-link-cable-tester-579f18c54565728c6efb50edee40ca27f86d2fcc.tar.gz
gba-link-cable-tester-579f18c54565728c6efb50edee40ca27f86d2fcc.zip
Implement subpixel precision for line drawing
-rw-r--r--src/main.c13
-rw-r--r--src/renderer_m0.c39
2 files changed, 25 insertions, 27 deletions
diff --git a/src/main.c b/src/main.c
index bd50a99..25e9893 100644
--- a/src/main.c
+++ b/src/main.c
@@ -126,12 +126,15 @@ int main(void) {
126 bios_vblank_wait(); 126 bios_vblank_wait();
127 127
128 PROF(test_clear(), test_clear_cycles); 128 PROF(test_clear(), test_clear_cycles);
129 // draw_line(0, 0, 50, 20, 2); 129 // draw_line(0, 0, 100, 31, 2);
130 // draw_line(0, 31, 100, 0, 5);
131 // txt_render();
132 // txt_clear();
130 PROF(test_lines(), test_lines_cycles); 133 PROF(test_lines(), test_lines_cycles);
131 PROF(test_rect(), test_rect_cycles); 134 // PROF(test_rect(), test_rect_cycles);
132 PROF(test_fill_rect(), test_fill_rect_cycles); 135 // PROF(test_fill_rect(), test_fill_rect_cycles);
133 PROF(test_chr(), test_chr_cycles); 136 // PROF(test_chr(), test_chr_cycles);
134 PROF(test_icn(), test_icn_cycles); 137 // PROF(test_icn(), test_icn_cycles);
135 draw_filled_rect(0, 0, 140, 60, 0); 138 draw_filled_rect(0, 0, 140, 60, 0);
136 PROF_SHOW(); 139 PROF_SHOW();
137 PROF(flip_buffer(), flip_cycles); 140 PROF(flip_buffer(), flip_cycles);
diff --git a/src/renderer_m0.c b/src/renderer_m0.c
index 94a3d9d..36ed01b 100644
--- a/src/renderer_m0.c
+++ b/src/renderer_m0.c
@@ -179,42 +179,37 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
179 draw_vline(x0, y0, y1, clr); 179 draw_vline(x0, y0, y1, clr);
180 } else { 180 } else {
181#if 1 181#if 1
182 int precision_bits = 6;
183 int precision_one = (1 << precision_bits);
184 int precision_half = precision_one >> 1;
182 int dx = x0 > x1 ? x0 - x1 : x1 - x0; 185 int dx = x0 > x1 ? x0 - x1 : x1 - x0;
183 int dy = y0 > y1 ? y0 - y1 : y1 - y0; 186 int dy = y0 > y1 ? y0 - y1 : y1 - y0;
187 int frac_x = x0 > x1 ? ((x0 - x1) << precision_bits) : ((x1 - x0) << precision_bits);
188 int frac_y = y0 > y1 ? ((y0 - y1) << precision_bits) : ((y1 - y0) << precision_bits);
184 int x_step = x0 > x1 ? -1 : 1; 189 int x_step = x0 > x1 ? -1 : 1;
185 int y_step = y0 > y1 ? -1 : 1; 190 int y_step = y0 > y1 ? -1 : 1;
191 int dxf = (dx << precision_bits);
192 int dyf = (dy << precision_bits);
186 if (dx >= dy) { 193 if (dx >= dy) {
187 // int diff = 2 * dy - dx; 194 int distance = (frac_y - precision_one) * dx - (frac_x - precision_half) * dy;
188 // int distance = dx * dy - (y1 - y0) * dx; 195 for (int i = 0; i <= dx; i++) {
189 int distance = (dy - dx) / 2; 196 if (distance >= 0) {
190 for (int i = 0; i < dx + 1; i++) { 197 distance -= 2 * dxf;
191 // Previous implementation (Tom Forsyth).
192 if (distance > dx / 2) {
193 distance -= dx;
194 y0 += y_step; 198 y0 += y_step;
195 } 199 }
196 draw_pixel(x0, y0, clr); 200 draw_pixel(x0, y0, clr);
197 distance += dy; 201 distance += 2 * dyf;
198 x0 += x_step; 202 x0 += x_step;
199
200 // Previous implementation, slightly faster.
201 // draw_pixel(x0, y0, clr);
202 // if (diff >= 0) {
203 // diff -= 2 * dx;
204 // y0 += y_step;
205 // }
206 // diff += 2 * dy;
207 // x0 += x_step;
208 } 203 }
209 } else { 204 } else {
210 int diff = 2 * dx - dy; 205 int distance = (frac_x - precision_one) * dy - (frac_y - precision_half) * dx;
211 for (int i = 0; i < dy + 1; i++) { 206 for (int i = 0; i <= dy; i++) {
212 draw_pixel(x0, y0, clr); 207 draw_pixel(x0, y0, clr);
213 if (diff >= 0) { 208 if (distance >= 0) {
214 diff -= 2 * dy; 209 distance -= 2 * dyf;
215 x0 += x_step; 210 x0 += x_step;
216 } 211 }
217 diff += 2 * dx; 212 distance += 2 * dxf;
218 y0 += y_step; 213 y0 += y_step;
219 } 214 }
220 } 215 }