software rendering
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 8 Jun 2023 17:40:42 +0000 (20:40 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 8 Jun 2023 17:40:42 +0000 (20:40 +0300)
src/app.c
src/darray.c [new file with mode: 0644]
src/darray.h [new file with mode: 0644]
src/gaw/gaw_sw.c
src/gaw/gaw_sw.h
src/gaw/gawswtnl.c
src/gaw/polyfill.c
src/gaw/polyfill.h
src/modern/main.c
src/scr_mod.c

index fdcbe11..9db63b0 100644 (file)
--- 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 (file)
index 0000000..225d3a0
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+Deep Runner - 6dof shooter game for the SGI O2.
+Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..ddfddf6
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Deep Runner - 6dof shooter game for the SGI O2.
+Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 <https://www.gnu.org/licenses/>.
+*/
+#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_ */
index 3df97f3..5e4619c 100644 (file)
@@ -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 <https://www.gnu.org/licenses/>.
 */
+#include <stdio.h>
 #include <string.h>
 #include "gaw.h"
 #include "gawswtnl.h"
@@ -319,8 +320,7 @@ void gaw_swtnl_drawprim(int prim, struct vertex *v, int vnum)
        for(i=0; i<vnum; i++) {
                /* viewport transformation */
                v[i].x = (v[i].x * 0.5f + 0.5f) * (float)ST->vport[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:
index 8b0791d..26ec205 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
 Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
 
 This program is free software: you can redistribute it and/or modify
index 5278754..5e55621 100644 (file)
@@ -532,12 +532,11 @@ void gaw_draw_indexed(int prim, const unsigned int *idxarr, int nidx)
                if(!vnum) continue;
 
                for(i=0; i<vnum; i++) {
-                       if(v[i].w != 0.0f) {
-                               v[i].x /= v[i].w;
-                               v[i].y /= v[i].w;
-                               if(st.opt & (1 << GAW_DEPTH_TEST)) {
-                                       v[i].z /= v[i].w;
-                               }
+                       float oow = 1.0f / v[i].w;
+                       v[i].x *= oow;
+                       v[i].y *= oow;
+                       if(st.opt & (1 << GAW_DEPTH_TEST)) {
+                               v[i].z *= oow;
                        }
                }
 
@@ -548,7 +547,7 @@ void gaw_draw_indexed(int prim, const unsigned int *idxarr, int nidx)
 void gaw_begin(int prim)
 {
        st.imm_prim = prim;
-       st.imm_pcount = prim;
+       st.imm_pcount = prim_vcount[st.imm_prim];
        st.imm_numv = 0;
 }
 
@@ -623,6 +622,7 @@ void gaw_vertex2f(float x, float y)
 void gaw_vertex3f(float x, float y, float z)
 {
        gaw_vertex4f(x, y, z, 1);
+}
 
 void gaw_vertex4f(float x, float y, float z, float w)
 {
index efdee71..15c06fb 100644 (file)
@@ -415,3 +415,58 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #include "polytmpl.h"
 #undef POLYFILL
 
+
+void draw_line(struct pvertex *verts)
+{
+       int32_t x0, y0, x1, y1;
+       int i, dx, dy, x_inc, y_inc, error;
+       uint32_t *fb = pfill_fb.pixels;
+       uint32_t color = PACK_RGB(verts[0].r, verts[0].g, verts[0].b);
+
+       x0 = verts[0].x >> 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;
+               }
+       }
+}
index b9173bc..fe24d82 100644 (file)
@@ -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_ */
index 066c431..c72b788 100644 (file)
@@ -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;
index 9dfedc7..12d0d1e 100644 (file)
@@ -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();
 }