From 5f50ec3c542ea29211591d4865bdaf1368f8c649 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 8 Jun 2023 20:40:42 +0300 Subject: [PATCH] software rendering --- src/app.c | 12 ++++- src/darray.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/darray.h | 65 ++++++++++++++++++++++++ src/gaw/gaw_sw.c | 5 +- src/gaw/gaw_sw.h | 2 +- src/gaw/gawswtnl.c | 14 +++--- src/gaw/polyfill.c | 55 +++++++++++++++++++++ src/gaw/polyfill.h | 4 +- src/modern/main.c | 4 +- src/scr_mod.c | 19 ++----- 10 files changed, 291 insertions(+), 28 deletions(-) create mode 100644 src/darray.c create mode 100644 src/darray.h diff --git a/src/app.c b/src/app.c index fdcbe11..9db63b0 100644 --- a/src/app.c +++ b/src/app.c @@ -72,6 +72,10 @@ int app_init(void) enable_fpexcept(); #endif +#ifdef GFX_SW + gaw_sw_init(); +#endif + load_options("retroray.cfg"); app_resize(opt.xres, opt.yres); app_vsync(opt.vsync); @@ -133,6 +137,10 @@ void app_shutdown(void) destroy_font(uifont); free(uifont); +#ifdef GFX_SW + gaw_sw_destroy(); +#endif + cleanup_logger(); } @@ -150,7 +158,9 @@ void app_reshape(int x, int y) int numpix = x * y; int prev_numpix = win_width * win_height; - if(numpix > prev_numpix) { + printf("reshape(%d, %d)\n", x, y); + + if(!framebuf || numpix > prev_numpix) { void *tmp; if(!(tmp = realloc(framebuf, numpix * sizeof *framebuf))) { errormsg("failed to resize framebuffer to %dx%d\n", x, y); diff --git a/src/darray.c b/src/darray.c new file mode 100644 index 0000000..225d3a0 --- /dev/null +++ b/src/darray.c @@ -0,0 +1,139 @@ +/* +Deep Runner - 6dof shooter game for the SGI O2. +Copyright (C) 2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include "darray.h" +#include "util.h" + + +/* The array descriptor keeps auxilliary information needed to manipulate + * the dynamic array. It's allocated adjacent to the array buffer. + */ +struct arrdesc { + int nelem, szelem; + int max_elem; + int bufsz; /* not including the descriptor */ +}; + +#define DESC(x) ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc))) + +void *darr_alloc(int elem, int szelem) +{ + struct arrdesc *desc; + + desc = malloc_nf(elem * szelem + sizeof *desc); + desc->nelem = desc->max_elem = elem; + desc->szelem = szelem; + desc->bufsz = elem * szelem; + return (char*)desc + sizeof *desc; +} + +void darr_free(void *da) +{ + if(da) { + free(DESC(da)); + } +} + +void *darr_resize_impl(void *da, int elem) +{ + int newsz; + struct arrdesc *desc; + + if(!da) return 0; + desc = DESC(da); + + newsz = desc->szelem * elem; + desc = realloc_nf(desc, newsz + sizeof *desc); + + desc->nelem = desc->max_elem = elem; + desc->bufsz = newsz; + return (char*)desc + sizeof *desc; +} + +int darr_empty(void *da) +{ + return DESC(da)->nelem ? 0 : 1; +} + +int darr_size(void *da) +{ + return DESC(da)->nelem; +} + + +void *darr_clear_impl(void *da) +{ + return darr_resize_impl(da, 0); +} + +/* stack semantics */ +void *darr_push_impl(void *da, void *item) +{ + struct arrdesc *desc; + int nelem; + + desc = DESC(da); + nelem = desc->nelem; + + if(nelem >= desc->max_elem) { + /* need to resize */ + int newsz = desc->max_elem ? desc->max_elem * 2 : 1; + + da = darr_resize_impl(da, newsz); + desc = DESC(da); + desc->nelem = nelem; + } + + if(item) { + memcpy((char*)da + desc->nelem * desc->szelem, item, desc->szelem); + } + desc->nelem++; + return da; +} + +void *darr_pop_impl(void *da) +{ + struct arrdesc *desc; + int nelem; + + desc = DESC(da); + nelem = desc->nelem; + + if(!nelem) return da; + + if(nelem <= desc->max_elem / 3) { + /* reclaim space */ + int newsz = desc->max_elem / 2; + + da = darr_resize_impl(da, newsz); + desc = DESC(da); + desc->nelem = nelem; + } + desc->nelem--; + + return da; +} + +void *darr_finalize(void *da) +{ + struct arrdesc *desc = DESC(da); + memmove(desc, da, desc->bufsz); + return desc; +} diff --git a/src/darray.h b/src/darray.h new file mode 100644 index 0000000..ddfddf6 --- /dev/null +++ b/src/darray.h @@ -0,0 +1,65 @@ +/* +Deep Runner - 6dof shooter game for the SGI O2. +Copyright (C) 2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef DYNAMIC_ARRAY_H_ +#define DYNAMIC_ARRAY_H_ + +void *darr_alloc(int elem, int szelem); +void darr_free(void *da); +void *darr_resize_impl(void *da, int elem); +#define darr_resize(da, elem) do { (da) = darr_resize_impl(da, elem); } while(0) + +int darr_empty(void *da); +int darr_size(void *da); + +void *darr_clear_impl(void *da); +#define darr_clear(da) do { (da) = darr_clear_impl(da); } while(0) + +/* stack semantics */ +void *darr_push_impl(void *da, void *item); +#define darr_push(da, item) do { (da) = darr_push_impl(da, item); } while(0) +void *darr_pop_impl(void *da); +#define darr_pop(da) do { (da) = darr_pop_impl(da); } while(0) + +/* Finalize the array. No more resizing is possible after this call. + * Use free() instead of dynarr_free() to deallocate a finalized array. + * Returns pointer to the finalized array. + * Complexity: O(n) + */ +void *darr_finalize(void *da); + +/* utility macros to push characters to a string. assumes and maintains + * the invariant that the last element is always a zero + */ +#define darr_strpush(da, c) \ + do { \ + char cnull = 0, ch = (char)(c); \ + (da) = dynarr_pop_impl(da); \ + (da) = dynarr_push_impl((da), &ch); \ + (da) = dynarr_push_impl((da), &cnull); \ + } while(0) + +#define darr_strpop(da) \ + do { \ + char cnull = 0; \ + (da) = dynarr_pop_impl(da); \ + (da) = dynarr_pop_impl(da); \ + (da) = dynarr_push_impl((da), &cnull); \ + } while(0) + + +#endif /* DYNAMIC_ARRAY_H_ */ diff --git a/src/gaw/gaw_sw.c b/src/gaw/gaw_sw.c index 3df97f3..5e4619c 100644 --- a/src/gaw/gaw_sw.c +++ b/src/gaw/gaw_sw.c @@ -15,6 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include #include #include "gaw.h" #include "gawswtnl.h" @@ -319,8 +320,7 @@ void gaw_swtnl_drawprim(int prim, struct vertex *v, int vnum) for(i=0; ivport[2] + ST->vport[0]; - v[i].y = (v[i].y * 0.5f + 0.5f) * (float)ST->vport[3] + ST->vport[1]; - v[i].y = pfill_fb.height - v[i].y - 1; + v[i].y = (v[i].y * -0.5f + 0.5f) * (float)ST->vport[3] + ST->vport[1] - 1; /* convert pos to 24.8 fixed point */ pv[i].x = cround64(v[i].x * 256.0f); @@ -362,6 +362,7 @@ void gaw_swtnl_drawprim(int prim, struct vertex *v, int vnum) break; case GAW_LINES: + draw_line(pv); break; default: diff --git a/src/gaw/gaw_sw.h b/src/gaw/gaw_sw.h index 8b0791d..26ec205 100644 --- a/src/gaw/gaw_sw.h +++ b/src/gaw/gaw_sw.h @@ -1,5 +1,5 @@ /* -Deep Runner - 6dof shooter game for the SGI O2. +RetroRay - integrated standalone vintage modeller/renderer Copyright (C) 2023 John Tsiombikas This program is free software: you can redistribute it and/or modify diff --git a/src/gaw/gawswtnl.c b/src/gaw/gawswtnl.c index 5278754..5e55621 100644 --- a/src/gaw/gawswtnl.c +++ b/src/gaw/gawswtnl.c @@ -532,12 +532,11 @@ void gaw_draw_indexed(int prim, const unsigned int *idxarr, int nidx) if(!vnum) continue; for(i=0; i> 8; + y0 = verts[0].y >> 8; + x1 = verts[1].x >> 8; + y1 = verts[1].y >> 8; + + fb += y0 * pfill_fb.width + x0; + + dx = x1 - x0; + dy = y1 - y0; + + if(dx >= 0) { + x_inc = 1; + } else { + x_inc = -1; + dx = -dx; + } + if(dy >= 0) { + y_inc = pfill_fb.width; + } else { + y_inc = -pfill_fb.width; + dy = -dy; + } + + if(dx > dy) { + error = dy * 2 - dx; + for(i=0; i<=dx; i++) { + *fb = color; + if(error >= 0) { + error -= dx * 2; + fb += y_inc; + } + error += dy * 2; + fb += x_inc; + } + } else { + error = dx * 2 - dy; + for(i=0; i<=dy; i++) { + *fb = color; + if(error >= 0) { + error -= dy * 2; + fb += x_inc; + } + error += dx * 2; + fb += y_inc; + } + } +} diff --git a/src/gaw/polyfill.h b/src/gaw/polyfill.h index b9173bc..fe24d82 100644 --- a/src/gaw/polyfill.h +++ b/src/gaw/polyfill.h @@ -81,7 +81,7 @@ enum { typedef uint32_t gaw_pixel; #define PACK_RGB(r, g, b) \ - (((r) << 16) | ((g) << 8) | (b)) + (0xff000000 | ((r) << 16) | ((g) << 8) | (b)) #define PACK_RGBA(r, g, b, a) \ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) #define UNPACK_R(pix) ((pix) & 0xff) @@ -151,4 +151,6 @@ void polyfill_add_gouraud_zbuf(struct pvertex *verts, int nverts); void polyfill_add_tex_flat_zbuf(struct pvertex *verts, int nverts); void polyfill_add_tex_gouraud_zbuf(struct pvertex *verts, int nverts); +void draw_line(struct pvertex *verts); + #endif /* POLYFILL_H_ */ diff --git a/src/modern/main.c b/src/modern/main.c index 066c431..c72b788 100644 --- a/src/modern/main.c +++ b/src/modern/main.c @@ -77,7 +77,9 @@ int main(int argc, char **argv) wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT"); #endif - app_reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)); + win_width = glutGet(GLUT_WINDOW_WIDTH); + win_height = glutGet(GLUT_WINDOW_HEIGHT); + win_aspect = (float)win_width / win_height; if(app_init() == -1) { return 1; diff --git a/src/scr_mod.c b/src/scr_mod.c index 9dfedc7..12d0d1e 100644 --- a/src/scr_mod.c +++ b/src/scr_mod.c @@ -137,17 +137,6 @@ static void mdl_display(void) draw_grid(); - gaw_begin(GAW_QUADS); - gaw_color3f(1, 0, 0); - gaw_vertex2f(-1, -1); - gaw_color3f(0, 1, 0); - gaw_vertex2f(1, -1); - gaw_color3f(0, 0, 1); - gaw_vertex2f(1, 1); - gaw_color3f(1, 1, 0); - gaw_vertex2f(-1, 1); - gaw_end(); - gaw_viewport(0, 0, win_width, win_height); } @@ -156,14 +145,14 @@ static void draw_grid(void) gaw_begin(GAW_LINES); gaw_color3f(0.5, 0, 0); gaw_vertex4f(0, 0, 0, 1); - gaw_vertex4f(-1, 0, 0, 0); + gaw_vertex4f(-100, 0, 0, 1); gaw_vertex4f(0, 0, 0, 1); - gaw_vertex4f(1, 0, 0, 0); + gaw_vertex4f(100, 0, 0, 1); gaw_color3f(0, 0.5, 0); gaw_vertex4f(0, 0, 0, 1); - gaw_vertex4f(0, 0, -1, 0); + gaw_vertex4f(0, 0, -100, 1); gaw_vertex4f(0, 0, 0, 1); - gaw_vertex4f(0, 0, 1, 0); + gaw_vertex4f(0, 0, 100, 1); gaw_end(); } -- 1.7.10.4