summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-17 08:45:27 +0200
committerBad Diode <bd@badd10de.dev>2023-04-17 08:45:27 +0200
commitfc83417ad04f19bfea4313cd811facf21d8dec9b (patch)
tree8cc86bb9338abc774fffe43bea24999d1a929c9b
parentaa04adf0d2068fb1ef96ac64edc07a92fedf6025 (diff)
downloadgba-link-cable-tester-fc83417ad04f19bfea4313cd811facf21d8dec9b.tar.gz
gba-link-cable-tester-fc83417ad04f19bfea4313cd811facf21d8dec9b.zip
Add improved version of simple bresenham line drawing
-rw-r--r--src/main.c1
-rw-r--r--src/renderer_m0.c176
2 files changed, 39 insertions, 138 deletions
diff --git a/src/main.c b/src/main.c
index 7e7dfd4..bd50a99 100644
--- a/src/main.c
+++ b/src/main.c
@@ -126,6 +126,7 @@ 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 PROF(test_lines(), test_lines_cycles); 130 PROF(test_lines(), test_lines_cycles);
130 PROF(test_rect(), test_rect_cycles); 131 PROF(test_rect(), test_rect_cycles);
131 PROF(test_fill_rect(), test_fill_rect_cycles); 132 PROF(test_fill_rect(), test_fill_rect_cycles);
diff --git a/src/renderer_m0.c b/src/renderer_m0.c
index 2cb7675..d66785a 100644
--- a/src/renderer_m0.c
+++ b/src/renderer_m0.c
@@ -99,11 +99,11 @@ draw_hline(size_t x0, size_t x1, size_t y0, u8 clr) {
99 // 3. Lines go through 3 or more tiles, first and last tiles use 99 // 3. Lines go through 3 or more tiles, first and last tiles use
100 // partial row updates, rows in the middle can write the entire 100 // partial row updates, rows in the middle can write the entire
101 // row. 101 // row.
102 size_t dx = tile_x1 - tile_x0; 102 size_t dtx = tile_x1 - tile_x0;
103 u32 *dst = &backbuf[tile_x0 * 8 + tile_y * 8 * 32 + start_row]; 103 u32 *dst = &backbuf[tile_x0 * 8 + tile_y * 8 * 32 + start_row];
104 if (dx < 1) { 104 if (dtx < 1) {
105 u32 mask = 0xFFFFFFFF; 105 u32 mask = 0xFFFFFFFF;
106 mask >>= (7 - end_col - dx) * 4; 106 mask >>= (7 - end_col - dtx) * 4;
107 mask &= 0xFFFFFFFF << start_col * 4; 107 mask &= 0xFFFFFFFF << start_col * 4;
108 u32 row = (0x11111111 * clr) & mask; 108 u32 row = (0x11111111 * clr) & mask;
109 *dst = (*dst & ~mask) | row; 109 *dst = (*dst & ~mask) | row;
@@ -114,7 +114,7 @@ draw_hline(size_t x0, size_t x1, size_t y0, u8 clr) {
114 u32 row = 0x11111111 * clr; 114 u32 row = 0x11111111 * clr;
115 *dst = (*dst & ~(mask << shift_left)) | (row << shift_left); 115 *dst = (*dst & ~(mask << shift_left)) | (row << shift_left);
116 dst += 8; 116 dst += 8;
117 for (size_t i = 1; i < dx; i++) { 117 for (size_t i = 1; i < dtx; i++) {
118 *dst = row; 118 *dst = row;
119 dst += 8; 119 dst += 8;
120 } 120 }
@@ -142,9 +142,9 @@ draw_vline(size_t x0, size_t y0, size_t y1, u8 clr) {
142 u32 *dst = &backbuf[tile_x * 8 + tile_y * 8 * 32 + start_row0]; 142 u32 *dst = &backbuf[tile_x * 8 + tile_y * 8 * 32 + start_row0];
143 u32 mask = 0x0000000F << shift_left; 143 u32 mask = 0x0000000F << shift_left;
144 u32 row = (0x11111111 * clr) & mask; 144 u32 row = (0x11111111 * clr) & mask;
145 u32 dy = tile_y1 - tile_y0; 145 u32 dty = tile_y1 - tile_y0;
146 if (dy < 1) { 146 if (dty < 1) {
147 for (size_t i = 0; i < y1 - y0; i++, dst++) { 147 for (size_t i = 0; i < (y1 - y0); i++, dst++) {
148 dst[0] = (dst[0] & ~mask) | row; 148 dst[0] = (dst[0] & ~mask) | row;
149 } 149 }
150 } else { 150 } else {
@@ -152,7 +152,7 @@ draw_vline(size_t x0, size_t y0, size_t y1, u8 clr) {
152 dst[0] = (dst[0] & ~mask) | row; 152 dst[0] = (dst[0] & ~mask) | row;
153 } 153 }
154 dst += 8 * 31; 154 dst += 8 * 31;
155 for (size_t j = 1; j < dy; j++) { 155 for (size_t j = 1; j < dty; j++) {
156 for (size_t i = 0; i < 8; i++, dst++) { 156 for (size_t i = 0; i < 8; i++, dst++) {
157 dst[0] = (dst[0] & ~mask) | row; 157 dst[0] = (dst[0] & ~mask) | row;
158 } 158 }
@@ -176,7 +176,7 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
176 MAYBE_SWAP(y0, y1); 176 MAYBE_SWAP(y0, y1);
177 draw_vline(x0, y0, y1, clr); 177 draw_vline(x0, y0, y1, clr);
178 } else { 178 } else {
179#if 1 179#if 0
180 // Diagonal line. 180 // Diagonal line.
181 int dx = x0 > x1 ? x0 - x1 : x1 - x0; 181 int dx = x0 > x1 ? x0 - x1 : x1 - x0;
182 int dy = y0 > y1 ? y1 - y0 : y0 - y1; 182 int dy = y0 > y1 ? y1 - y0 : y0 - y1;
@@ -196,135 +196,35 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
196 } 196 }
197 } 197 }
198#else 198#else
199 // int dx = x0 > x1 ? x0 - x1 : x1 - x0; 199 int dx = x0 > x1 ? x0 - x1 : x1 - x0;
200 // int dy = y0 > y1 ? y0 - y1 : y1 - y0; 200 int dy = y0 > y1 ? y0 - y1 : y1 - y0;
201 // int x_step = x0 > x1 ? -1 : 1; 201 int x_step = x0 > x1 ? -1 : 1;
202 // int y_step = y0 > y1 ? -SCREEN_WIDTH : SCREEN_WIDTH; 202 int y_step = y0 > y1 ? -1 : 1;
203 203 if (dx >= dy) {
204 // u16 *dst = NULL; 204 int diff = 2 * dy - dx;
205 // uintptr_t addr = ((uintptr_t)backbuf + y0 * SCREEN_WIDTH + x0); 205 for (int i = 0; i < dx + 1; i++) {
206 // u32 mask = x0 & 1 ? ~0xFF : 0xFF; 206 draw_pixel(x0, y0, clr);
207 // u32 color = (clr & 0xFF) | ((clr & 0xFF) << 8); 207 if (diff >= 0) {
208 // if (dx >= dy) { 208 diff -= 2 * dx;
209 // int diff = 2 * dy - dx; 209 y0 += y_step;
210 // for (int i = 0; i < dx + 1; i++) { 210 }
211 // dst = (u16 *)(addr - (mask >> 31)); 211 diff += 2 * dy;
212 // *dst = (*dst & ~mask) | (color & mask); 212 x0 += x_step;
213 // if (diff >= 0) { 213 }
214 // diff -= 2 * dx; 214 } else {
215 // addr += y_step; 215 int diff = 2 * dx - dy;
216 // } 216 for (int i = 0; i < dy + 1; i++) {
217 // diff += 2 * dy; 217 draw_pixel(x0, y0, clr);
218 // addr += x_step; 218 if (diff >= 0) {
219 // mask = ~mask; 219 diff -= 2 * dy;
220 // } 220 x0 += x_step;
221 // } else { 221 }
222 // int diff = 2 * dx - dy; 222 diff += 2 * dx;
223 // for (int i = 0; i < dy + 1; i++) { 223 y0 += y_step;
224 // dst = (u16 *)(addr - (mask >> 31)); 224 }
225 // *dst = (*dst & ~mask) | (color & mask); 225 }
226 // if (diff >= 0) {
227 // diff -= 2 * dy;
228 // addr += x_step;
229 // mask = ~mask;
230 // }
231 // diff += 2 * dx;
232 // addr += y_step;
233 // }
234 // }
235#endif 226#endif
236 } 227 }
237
238 // // Find row positions for the given x/y coordinates.
239 // size_t tile_x0 = x0 / 8;
240 // size_t tile_y0 = y0 / 8;
241 // size_t tile_x1 = x1 / 8;
242 // size_t tile_y1 = y1 / 8;
243 // size_t start_col0 = x0 % 8;
244 // size_t start_col1 = x1 % 8;
245 // size_t start_row0 = y0 % 8;
246 // size_t start_row1 = y1 % 8;
247
248 // // Get a pointer to the backbuffer and the tile row.
249 // u32 *backbuffer = &BACKBUF[start_row0 + (tile_x0 + tile_y0 * 32) * 8];
250
251 // if (y0 == y1) {
252 // // Horizontal line. There are 3 cases:
253 // // 1. Lines fit on a single tile.
254 // // 2. Lines go through 2 tiles, both require partial row updates.
255 // // 3. Lines go through 3 or more tiles, first and last tiles use
256 // // partial row updates, rows in the middle can write the.
257 // size_t dx = tile_x1 - tile_x0;
258 // if (dx < 1) {
259 // u32 row_mask = 0xFFFFFFFF;
260 // row_mask >>= (7 - start_col1 - dx) * 4;
261 // row_mask &= 0xFFFFFFFF << start_col0 * 4;
262 // u32 row = (0x11111111 * clr) & row_mask;
263 // backbuffer[0] = (backbuffer[0] & ~row_mask) | row;
264 // dirty_tiles[tile_y0] |= 1 << tile_x0;
265 // } else {
266 // size_t shift_left = start_col0 * 4;
267 // size_t shift_right = (7 - start_col1) * 4;
268 // u32 row_mask = 0xFFFFFFFF;
269 // u32 row = 0x11111111 * clr;
270 // backbuffer[0] = backbuffer[0] & ~(row_mask << shift_left);
271 // backbuffer[0] |= row << shift_left;
272 // dirty_tiles[tile_y0] |= 1 << tile_x0;
273 // for (size_t i = 1; i < dx; i++) {
274 // backbuffer[i * 8] = row;
275 // dirty_tiles[tile_y0] |= 1 << (tile_x0 + i);
276 // }
277 // backbuffer[dx * 8] = backbuffer[dx * 8] & ~(row_mask >> shift_right);
278 // backbuffer[dx * 8] |= row >> shift_right;
279 // dirty_tiles[tile_y0] |= 1 << (tile_x0 + dx);
280 // }
281 // } else if (x0 == x1) {
282 // // Vertical line. The cases are analogous to the horizontal ones.
283 // size_t dy = tile_y1 - tile_y0;
284 // u32 row_mask = 0xF << start_col0 * 4;
285 // u32 row_left = (0x11111111 * clr) & row_mask;
286 // if (dy < 1) {
287 // for (size_t i = 0; i <= y1 - y0; i++, backbuffer++) {
288 // backbuffer[0] = (backbuffer[0] & ~row_mask) | row_left;
289 // }
290 // } else {
291 // for (size_t i = 0; i < (8 - start_row0); i++, backbuffer++) {
292 // backbuffer[0] = (backbuffer[0] & ~row_mask) | row_left;
293 // }
294 // dirty_tiles[tile_y0] |= 1 << tile_x0;
295 // backbuffer += 8 * 31;
296 // for (size_t j = 1; j < dy; j++) {
297 // for (size_t i = 0; i < 8; i++, backbuffer++) {
298 // backbuffer[0] = (backbuffer[0] & ~row_mask) | row_left;
299 // }
300 // backbuffer += 8 * 31;
301 // dirty_tiles[tile_y0 + j] |= 1 << tile_x0;
302 // }
303 // for (size_t i = 0; i <= start_row1; i++, backbuffer++) {
304 // backbuffer[0] = (backbuffer[0] & ~row_mask) | row_left;
305 // }
306 // dirty_tiles[tile_y1] |= 1 << tile_x0;
307 // }
308 // } else {
309 // // Diagonal line.
310 // int dx = x0 > x1 ? x0 - x1 : x1 - x0;
311 // int dy = y0 > y1 ? y1 - y0 : y0 - y1;
312 // int x_step = x0 < x1 ? 1 : -1;
313 // int y_step = y0 < y1 ? 1 : -1;
314 // int err = dx + dy;
315 // while (!(x0 == x1 && y0 == y1)) {
316 // draw_pixel(x0, y0, clr);
317 // int diff = 2 * err;
318 // if (diff >= dy) {
319 // err += dy;
320 // x0 += x_step;
321 // }
322 // if (diff <= dx) {
323 // err += dx;
324 // y0 += y_step;
325 // }
326 // }
327 // }
328} 228}
329 229
330IWRAM_CODE 230IWRAM_CODE
@@ -399,7 +299,7 @@ draw_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
399 // u32 cur_row = start_row0; 299 // u32 cur_row = start_row0;
400 // dst0 = &backbuf[start_row0 + (tile_x0 + tile_y0 * 32) * 8]; 300 // dst0 = &backbuf[start_row0 + (tile_x0 + tile_y0 * 32) * 8];
401 // dst1 = &backbuf[start_row0 + (tile_x1 + tile_y0 * 32) * 8]; 301 // dst1 = &backbuf[start_row0 + (tile_x1 + tile_y0 * 32) * 8];
402 // for (size_t i = 0; i <= y1 - y0; i++) { 302 // for (size_t i = 0; i <= (y1 - y0); i++) {
403 // *dst0 = (*dst0 & ~mask_left) | row_left; 303 // *dst0 = (*dst0 & ~mask_left) | row_left;
404 // *dst1 = (*dst1 & ~mask_right) | row_right; 304 // *dst1 = (*dst1 & ~mask_right) | row_right;
405 // if (cur_row == 7) { 305 // if (cur_row == 7) {
@@ -413,7 +313,7 @@ draw_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
413 // } 313 // }
414 // } 314 // }
415 if (dy < 1) { 315 if (dy < 1) {
416 for (size_t i = 1; i < y1 - y0; i++, dst0++) { 316 for (size_t i = 1; i < (y1 - y0); i++, dst0++) {
417 dst0[1] = (dst0[1] & ~mask_left) | row_left; 317 dst0[1] = (dst0[1] & ~mask_left) | row_left;
418 dst0[1 + 8 * dx] = (dst0[1 + 8 * dx] & ~mask_right) | row_right; 318 dst0[1 + 8 * dx] = (dst0[1 + 8 * dx] & ~mask_right) | row_right;
419 } 319 }