diff options
author | Bad Diode <bd@badd10de.dev> | 2023-04-17 18:08:39 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-04-17 18:08:39 +0200 |
commit | 4b5be795ea7f177d5e343b9f75eff781667cd301 (patch) | |
tree | a27e2068facadfbe794afcb46a07ad6427f205c5 | |
parent | 1d176dac4f3fc511693c5924affc553637b14879 (diff) | |
download | gba-renderers-4b5be795ea7f177d5e343b9f75eff781667cd301.tar.gz gba-renderers-4b5be795ea7f177d5e343b9f75eff781667cd301.zip |
Experiment with a more performant basic bresenham
-rw-r--r-- | src/main.c | 20 | ||||
-rw-r--r-- | src/renderer_m0.c | 107 |
2 files changed, 87 insertions, 40 deletions
@@ -130,17 +130,17 @@ int main(void) { | |||
130 | 130 | ||
131 | // DX is bigger | 131 | // DX is bigger |
132 | // left -> right && top -> bot | 132 | // left -> right && top -> bot |
133 | //draw_line(0, 0, 239, 159, 1); | 133 | //PROF(draw_line(0, 0, 239, 159, 1), test_lines_cycles); |
134 | //// draw_line(10, 0, 229, 159, 1); | 134 | ////// draw_line(10, 0, 229, 159, 1); |
135 | //// left -> right && bot -> top | 135 | ////// left -> right && bot -> top |
136 | //draw_line(0, 159, 239, 0, 2); | 136 | //draw_line(0, 159, 239, 0, 2); |
137 | //// draw_line(10, 159, 229, 0, 2); | 137 | ////// draw_line(10, 159, 229, 0, 2); |
138 | //// | 138 | ////// |
139 | //draw_line(0, 0, 239, 159, 1); | 139 | ////draw_line(0, 0, 239, 159, 1); |
140 | //draw_line(0, 129, 239, 40, 2); | 140 | ////draw_line(0, 129, 239, 40, 2); |
141 | //// right -> left && top -> bot | 141 | ////// right -> left && top -> bot |
142 | //draw_line(239, 81, 0, 129, 3); | 142 | //draw_line(239, 81, 0, 129, 3); |
143 | //// right -> left && bot -> top | 143 | ////// right -> left && bot -> top |
144 | //draw_line(239, 129, 0, 40, 5); | 144 | //draw_line(239, 129, 0, 40, 5); |
145 | // txt_render(); | 145 | // txt_render(); |
146 | // txt_clear(); | 146 | // txt_clear(); |
@@ -162,7 +162,7 @@ int main(void) { | |||
162 | // PROF(test_fill_rect(), test_fill_rect_cycles); | 162 | // PROF(test_fill_rect(), test_fill_rect_cycles); |
163 | // PROF(test_chr(), test_chr_cycles); | 163 | // PROF(test_chr(), test_chr_cycles); |
164 | // PROF(test_icn(), test_icn_cycles); | 164 | // PROF(test_icn(), test_icn_cycles); |
165 | // draw_filled_rect(0, 0, 140, 60, 0); | 165 | draw_filled_rect(0, 0, 140, 60, 0); |
166 | PROF_SHOW(); | 166 | PROF_SHOW(); |
167 | PROF(flip_buffer(), flip_cycles); | 167 | PROF(flip_buffer(), flip_cycles); |
168 | } | 168 | } |
diff --git a/src/renderer_m0.c b/src/renderer_m0.c index 593dd10..ce9cfc8 100644 --- a/src/renderer_m0.c +++ b/src/renderer_m0.c | |||
@@ -179,6 +179,81 @@ 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 | |||
183 | // Fixed Precision constants. | ||
184 | const int fp_bit = 6; | ||
185 | const int fp_one = FP_NUM(1, fp_bit); | ||
186 | const int fp_half = fp_one >> 1; | ||
187 | |||
188 | int dx = x0 > x1 ? x0 - x1 : x1 - x0; | ||
189 | int dy = y0 > y1 ? y0 - y1 : y1 - y0; | ||
190 | int dxf = (dx << fp_bit); | ||
191 | int dyf = (dy << fp_bit); | ||
192 | |||
193 | if ((dx >= dy && x0 > x1) || (dx < dy && y0 > y1)) { | ||
194 | SWAP(x0, x1); | ||
195 | SWAP(y0, y1); | ||
196 | } | ||
197 | |||
198 | int frac_x = x0 > x1 ? FP_NUM(x0 - x1, fp_bit) : FP_NUM(x1 - x0, fp_bit); | ||
199 | int frac_y = y0 > y1 ? FP_NUM(y0 - y1, fp_bit) : FP_NUM(y1 - y0, fp_bit); | ||
200 | int x_step = x0 > x1 ? -1 : 1; | ||
201 | int y_step = y0 > y1 ? -1 : 1; | ||
202 | int distance = (frac_y - fp_one) * dx - (frac_x - fp_half) * dy; | ||
203 | |||
204 | // | ||
205 | // DEBUG: reference | ||
206 | // for (int i = 0; i <= dx; i++) { | ||
207 | // if (distance >= 0) { | ||
208 | // distance -= 2 * dxf; | ||
209 | // y0 += y_step; | ||
210 | // } | ||
211 | // draw_pixel(x0, y0, clr); | ||
212 | // distance += 2 * dyf; | ||
213 | // x0 += x_step; | ||
214 | // } | ||
215 | // | ||
216 | |||
217 | size_t tile_x = x0 / 8; | ||
218 | size_t tile_y = y0 / 8; | ||
219 | size_t start_col = x0 % 8; | ||
220 | size_t start_row = y0 % 8; | ||
221 | u32 *dst = &backbuf[start_row + (tile_x + tile_y * 32) * 8]; | ||
222 | |||
223 | // Update backbuffer. | ||
224 | if (dx >= dy) { | ||
225 | for (int i = 0; i <= dx; i++) { | ||
226 | start_col = x0 % 8; | ||
227 | start_row = y0 % 8; | ||
228 | size_t shift = start_col * sizeof(u32); | ||
229 | u32 mask = 0xF << shift; | ||
230 | u32 row = clr << shift; | ||
231 | if (distance >= 0) { | ||
232 | distance -= 2 * dxf; | ||
233 | y0 += y_step; | ||
234 | if (((int)start_row + y_step) >= 8 || ((int)start_row + y_step) < 0) { | ||
235 | dst += 8 * 31 * y_step; | ||
236 | } | ||
237 | dst += y_step; | ||
238 | } | ||
239 | *dst = (*dst & ~mask) | row; | ||
240 | distance += 2 * dyf; | ||
241 | if ((int)(start_col + x_step) >= 8 ||(int)(start_col + x_step) < 0) { | ||
242 | dst += 8; | ||
243 | } | ||
244 | x0 += x_step; | ||
245 | } | ||
246 | // for (int i = 0; i <= dx; i++) { | ||
247 | // if (distance >= 0) { | ||
248 | // distance -= 2 * dxf; | ||
249 | // y0 += y_step; | ||
250 | // } | ||
251 | // draw_pixel(x0, y0, clr); | ||
252 | // distance += 2 * dyf; | ||
253 | // x0 += x_step; | ||
254 | // } | ||
255 | } | ||
256 | #else | ||
182 | // Fixed Precision constants. | 257 | // Fixed Precision constants. |
183 | const int fp_bit = 6; | 258 | const int fp_bit = 6; |
184 | const int fp_one = FP_NUM(1, fp_bit); | 259 | const int fp_one = FP_NUM(1, fp_bit); |
@@ -200,7 +275,7 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { | |||
200 | int y_step = y0 > y1 ? -1 : 1; | 275 | int y_step = y0 > y1 ? -1 : 1; |
201 | int distance = (frac_y - fp_one) * dx - (frac_x - fp_half) * dy; | 276 | int distance = (frac_y - fp_one) * dx - (frac_x - fp_half) * dy; |
202 | if (dx >= dy) { | 277 | if (dx >= dy) { |
203 | int step = dx / dy; | 278 | int step = dxf / dyf; |
204 | int remaining = dx; | 279 | int remaining = dx; |
205 | while (remaining > (step - 1)) { | 280 | while (remaining > (step - 1)) { |
206 | distance += step * 2 * dyf; | 281 | distance += step * 2 * dyf; |
@@ -224,7 +299,7 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { | |||
224 | draw_hline(x0, x0 + remaining, y0, clr); | 299 | draw_hline(x0, x0 + remaining, y0, clr); |
225 | } | 300 | } |
226 | } else { | 301 | } else { |
227 | int step = dy / dx; | 302 | int step = dyf / dxf; |
228 | int remaining = dy; | 303 | int remaining = dy; |
229 | while (remaining > (step - 1)) { | 304 | while (remaining > (step - 1)) { |
230 | distance += step * 2 * dxf; | 305 | distance += step * 2 * dxf; |
@@ -245,34 +320,6 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { | |||
245 | draw_vline(x0, y0, y0 + remaining, clr); | 320 | draw_vline(x0, y0, y0 + remaining, clr); |
246 | } | 321 | } |
247 | } | 322 | } |
248 | #else | ||
249 | int dx = x0 > x1 ? x0 - x1 : x1 - x0; | ||
250 | int dy = y0 > y1 ? y0 - y1 : y1 - y0; | ||
251 | int x_step = x0 > x1 ? -1 : 1; | ||
252 | int y_step = y0 > y1 ? -1 : 1; | ||
253 | if (dx >= dy) { | ||
254 | int diff = 2 * dy - dx; | ||
255 | for (int i = 0; i < dx + 1; i++) { | ||
256 | draw_pixel(x0, y0, clr); | ||
257 | if (diff >= 0) { | ||
258 | diff -= 2 * dx; | ||
259 | y0 += y_step; | ||
260 | } | ||
261 | diff += 2 * dy; | ||
262 | x0 += x_step; | ||
263 | } | ||
264 | } else { | ||
265 | int diff = 2 * dx - dy; | ||
266 | for (int i = 0; i < dy + 1; i++) { | ||
267 | draw_pixel(x0, y0, clr); | ||
268 | if (diff >= 0) { | ||
269 | diff -= 2 * dy; | ||
270 | x0 += x_step; | ||
271 | } | ||
272 | diff += 2 * dx; | ||
273 | y0 += y_step; | ||
274 | } | ||
275 | } | ||
276 | #endif | 323 | #endif |
277 | } | 324 | } |
278 | } | 325 | } |